aboutsummaryrefslogtreecommitdiff
path: root/forest/src/bytes.rs
diff options
context:
space:
mode:
Diffstat (limited to 'forest/src/bytes.rs')
-rw-r--r--forest/src/bytes.rs261
1 files changed, 243 insertions, 18 deletions
diff --git a/forest/src/bytes.rs b/forest/src/bytes.rs
index d0d7e1e..6e854c8 100644
--- a/forest/src/bytes.rs
+++ b/forest/src/bytes.rs
@@ -65,18 +65,18 @@
//! Each label has 3 parts:
//!
//! 1. Status: either Packed, Cloned, or Plain. If the node is
-//! cloned, it has a clone index. So in total this part occupies 1
-//! byte for the status and 8 bytes for the clone index.
+//! cloned, it has a clone index. So in total this part occupies 1
+//! byte for the status and 8 bytes for the clone index.
//! 2. Start and end: the range in the input sentence. We just store
-//! two numbers here. Hence this part occupies 16 bytes.
+//! two numbers here. Hence this part occupies 16 bytes.
//! 3. Grammar label: either a terminal, a non-terminal, or a rule.
-//! Each variant needs a number to speify its index. So in total this
-//! part occupies 1 byte for the variant discriminant and 8 bytes for
-//! the number.
+//! Each variant needs a number to speify its index. So in total
+//! this part occupies 1 byte for the variant discriminant and 8
+//! bytes for the number.
//!
//! To sum up, each label occupies 34 bytes.
-use super::Forest;
+use super::{Forest, ForestLabel, ForestLabelType};
use grammar::{GrammarLabel, GrammarLabelType, TNT};
use graph::error::Error as GError;
@@ -95,13 +95,16 @@ pub fn forest_to_bytes<F: Forest<GrammarLabel>>(forest: &F) -> Vec<u8> {
let total_degree: usize = degrees.iter().copied().sum();
- let len: usize = 8 // total number of bytes at the start
+ let label_offset: usize = 8 // total number of bytes = len
+ 3 // special mark
+ 8 // number of nodes
+ 8 // offset of labels
+ 16 * nodes_len // degree & offset for each node
+ 8 * total_degree // children of each node
- + 34 * nodes_len // labels
+ ;
+
+ let len: usize = label_offset // see that variable for details.
+ + 34 * nodes_len // labels
;
// Then fill in the bytes.
@@ -113,17 +116,18 @@ pub fn forest_to_bytes<F: Forest<GrammarLabel>>(forest: &F) -> Vec<u8> {
bytes.extend(len.to_be_bytes());
bytes.extend([114, 101, 112]); // rep
bytes.extend(nodes_len.to_be_bytes());
- bytes.extend((len - 34 * nodes_len).to_be_bytes());
+ bytes.extend(label_offset.to_be_bytes());
- let mut accumulated: usize = 0;
+ let mut accumulated: usize = 8 + 3 + 8 + 8 + 16 * nodes_len;
// Then degrees and offsets
for degree in degrees.iter().copied() {
bytes.extend(degree.to_be_bytes());
- bytes.extend((8 + 3 + 8 + 8 + 16 * nodes_len + 8 * accumulated).to_be_bytes());
+ bytes.extend(accumulated.to_be_bytes());
+ // bytes.extend((8 + 3 + 8 + 8 + 16 * nodes_len + 8 * accumulated).to_be_bytes());
- accumulated += degree;
+ accumulated += 8 * degree;
}
// Then the children
@@ -337,43 +341,147 @@ impl TryFrom<Vec<u8>> for BytesForest {
pub struct BytesChildrenIter<'a> {
vec: &'a [u8],
offset: usize,
+ label_offset: usize,
degree: usize,
current: usize,
}
+/// The delegation of iterators for children and labels of nodes.
+#[derive(Debug, Clone)]
+pub struct BytesLabelChildrenIter<'a>(BytesChildrenIter<'a>);
+
+impl<'a> Iterator for BytesLabelChildrenIter<'a> {
+ type Item = (ForestLabel<GrammarLabel>, usize);
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ let iter = &self.0;
+
+ if iter.current >= iter.degree {
+ return None;
+ }
+
+ let len = iter.vec.len();
+
+ if iter.offset + 8 * iter.degree >= len {
+ dbg!();
+ return None;
+ }
+
+ if iter.label_offset + 34 * iter.degree > len {
+ dbg!();
+ return None;
+ }
+
+ let result_index = usize::from_be_bytes(
+ (&iter.vec[(iter.offset + 8 * iter.current)..(iter.offset + 8 * iter.current + 8)])
+ .try_into()
+ .ok()?,
+ );
+
+ let result_label = read_label(
+ &iter.vec[(iter.label_offset + iter.current * 34)
+ ..(iter.label_offset + iter.current * 34 + 34)],
+ )
+ .ok()?;
+
+ self.0.current += 1;
+
+ Some((result_label, result_index))
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.0.degree, Some(self.0.degree))
+ }
+}
+
+impl<'a> ExactSizeIterator for BytesLabelChildrenIter<'a> {
+ #[inline]
+ fn len(&self) -> usize {
+ self.0.degree
+ }
+}
+
impl<'a> Iterator for BytesChildrenIter<'a> {
type Item = usize;
+ #[inline]
fn next(&mut self) -> Option<Self::Item> {
- if self.current + 1 >= self.degree {
+ if self.current >= self.degree {
return None;
}
let len = self.vec.len();
- if self.offset + 8 * self.degree > len {
+ if self.offset + 8 * self.degree >= len {
dbg!();
return None;
}
- Some(usize::from_be_bytes(
+ let result = usize::from_be_bytes(
(&self.vec[(self.offset + 8 * self.current)..(self.offset + 8 * self.current + 8)])
.try_into()
.ok()?,
- ))
+ );
+
+ self.current += 1;
+
+ Some(result)
}
+ #[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
(self.degree, Some(self.degree))
}
}
impl<'a> ExactSizeIterator for BytesChildrenIter<'a> {
+ #[inline]
fn len(&self) -> usize {
self.degree
}
}
+fn read_label(data: &[u8]) -> Result<ForestLabel<GrammarLabel>, GError> {
+ let len = data.len();
+
+ if len < 34 {
+ return Err(GError::IndexOutOfBounds(34, len));
+ }
+
+ let pack_status: ForestLabelType = match data.first().copied().unwrap() {
+ 0 => ForestLabelType::Plain,
+ 1 => ForestLabelType::Packed,
+ _ => ForestLabelType::Cloned(usize::from_be_bytes(
+ data[1..9].try_into().expect("should not happen"),
+ )),
+ };
+
+ let start = usize::from_be_bytes(data[9..17].try_into().expect("should not happen"));
+ let end = usize::from_be_bytes(data[17..25].try_into().expect("should not happen"));
+
+ let grammarlabeltype = match data.get(25).unwrap() {
+ 0 => GrammarLabelType::TNT(TNT::Ter(usize::from_be_bytes(
+ data[26..34].try_into().expect("should not happen"),
+ ))),
+ 1 => GrammarLabelType::TNT(TNT::Non(usize::from_be_bytes(
+ data[26..34].try_into().expect("should not happen"),
+ ))),
+ _ => GrammarLabelType::Rule(usize::from_be_bytes(
+ data[26..34].try_into().expect("should not happen"),
+ )),
+ };
+
+ let label = if end == 0 {
+ GrammarLabel::new(grammarlabeltype, start)
+ } else {
+ GrammarLabel::new_closed(grammarlabeltype, start, end)
+ };
+
+ Ok(ForestLabel::new(label, pack_status))
+}
+
impl graph::Graph for BytesForest {
type Iter<'a> = BytesChildrenIter<'a>
where
@@ -404,6 +512,8 @@ impl graph::Graph for BytesForest {
.unwrap(),
);
+ let label_offset = usize::from_be_bytes((&self.bytes[19..27]).try_into().unwrap());
+
let current = 0;
let vec = &self.bytes;
@@ -411,6 +521,7 @@ impl graph::Graph for BytesForest {
Ok(BytesChildrenIter {
vec,
offset,
+ label_offset,
degree,
current,
})
@@ -453,4 +564,118 @@ impl graph::Graph for BytesForest {
}
}
-// TODO: Implement labelgraph
+impl graph::VLabelGraph<ForestLabel<GrammarLabel>> for BytesForest {
+ type TupleIter<'a> = BytesLabelChildrenIter<'a>
+ where
+ Self: 'a,
+ ForestLabel<GrammarLabel>: 'a;
+
+ fn verlabren_of(&self, node_id: usize) -> Result<Self::TupleIter<'_>, GError> {
+ if node_id >= self.nodes_len {
+ return Err(GError::IndexOutOfBounds(node_id, self.nodes_len));
+ }
+
+ let degree = usize::from_be_bytes(
+ (&self.bytes[(27 + 16 * node_id)..(35 + 16 * node_id)])
+ .try_into()
+ .unwrap(),
+ );
+
+ let offset = usize::from_be_bytes(
+ (&self.bytes[(35 + 16 * node_id)..(43 + 16 * node_id)])
+ .try_into()
+ .unwrap(),
+ );
+
+ let label_offset = usize::from_be_bytes((&self.bytes[19..27]).try_into().unwrap());
+
+ let current = 0;
+
+ let vec = &self.bytes;
+
+ Ok(BytesLabelChildrenIter(BytesChildrenIter {
+ vec,
+ offset,
+ label_offset,
+ degree,
+ current,
+ }))
+ }
+}
+
+impl graph::LabelGraph<ForestLabel<GrammarLabel>> for BytesForest {
+ fn query_label(&self, label: ForestLabel<GrammarLabel>) -> Option<usize> {
+ use graph::Graph;
+ let nodes_len = self.nodes_len();
+
+ for index in 0..nodes_len {
+ let index_label = read_label(
+ &self.bytes[(self.offset + index * 34)..(self.offset + index * 34 + 34)],
+ )
+ .ok()?;
+
+ if index_label == label {
+ return Some(index);
+ }
+ }
+
+ None
+ }
+
+ fn vertex_label(&self, node_id: usize) -> Result<Option<ForestLabel<GrammarLabel>>, GError> {
+ read_label(&self.bytes[(self.offset + node_id * 34)..(self.offset + node_id * 34 + 34)])
+ .map(Some)
+ }
+
+ type Iter<'a> = std::iter::Empty<usize>
+ where
+ Self: 'a;
+
+ type TupleIter<'a>=std::iter::Empty<(ForestLabel<GrammarLabel>, usize)>
+ where
+ Self: 'a,
+ ForestLabel<GrammarLabel>: 'a;
+
+ type LabelIter<'a> = std::iter::Empty<(&'a ForestLabel<GrammarLabel>, std::iter::Empty<usize>)>
+ where
+ Self: 'a,
+ ForestLabel<GrammarLabel>: 'a;
+
+ type EdgeLabelIter<'a> = std::iter::Empty<ForestLabel<GrammarLabel>>
+ where
+ Self: 'a,
+ ForestLabel<GrammarLabel>: 'a;
+
+ fn edge_label(
+ &self,
+ _source: usize,
+ _target: usize,
+ ) -> Result<Self::EdgeLabelIter<'_>, GError> {
+ unimplemented!("bytes forests do not have edge labels")
+ }
+
+ fn find_children_with_label(
+ &self,
+ _node_id: usize,
+ _label: &ForestLabel<GrammarLabel>,
+ ) -> Result<<Self as graph::LabelGraph<ForestLabel<GrammarLabel>>>::Iter<'_>, GError> {
+ unimplemented!("bytes forests do not have edge labels")
+ }
+
+ fn labels_of(&self, _node_id: usize) -> Result<Self::LabelIter<'_>, GError> {
+ unimplemented!("bytes forests do not have edge labels")
+ }
+
+ fn tuples_of(&self, _node_id: usize) -> Result<Self::TupleIter<'_>, GError> {
+ unimplemented!("bytes forests do not have edge labels")
+ }
+
+ fn has_edge_label(
+ &self,
+ _node_id: usize,
+ _label: &ForestLabel<GrammarLabel>,
+ _target: usize,
+ ) -> Result<bool, GError> {
+ unimplemented!("bytes forests do not have edge labels")
+ }
+}