Skip to content

Commit

Permalink
Support parsing array/sequence
Browse files Browse the repository at this point in the history
Signed-off-by: Gris Ge <[email protected]>
  • Loading branch information
cathay4t committed Dec 27, 2024
1 parent d8fc946 commit 26b8f43
Show file tree
Hide file tree
Showing 6 changed files with 296 additions and 88 deletions.
92 changes: 92 additions & 0 deletions src/array.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// SPDX-License-Identifier: Apache-2.0

use serde::de::{DeserializeSeed, SeqAccess};

use crate::{
RmsdDeserializer, RmsdError, TokensIter, YamlToken, YamlTokenData,
YamlValue,
};

pub(crate) fn get_array(
iter: &mut TokensIter,
) -> Result<Vec<YamlValue>, RmsdError> {
let mut ret: Vec<YamlValue> = Vec::new();

let indent = if let Some(first_token) = iter.peek() {
first_token.indent
} else {
return Ok(ret);
};

while let Some(token) = iter.peek() {
if token.indent < indent {
return Ok(ret);
}
if token.data == YamlTokenData::BlockSequenceIndicator {
iter.next();
let entry_tokens = get_seq_element_tokens(iter, indent);
ret.push(YamlValue::try_from(entry_tokens)?);
}
}

Ok(ret)
}

/// Take token until:
/// * indent miss-match
/// * reach another `-` with the same indent
fn get_seq_element_tokens(
iter: &mut TokensIter,
indent: usize,
) -> Vec<YamlToken> {
let mut ret = Vec::new();
while let Some(token) = iter.peek() {
if token.indent < indent
|| token.data == YamlTokenData::BlockSequenceIndicator
{
return ret;
} else {
let token = iter.next().unwrap();
ret.push(token);
}
}
ret
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct YamlValueSeqAccess {
data: Vec<YamlValue>,
}

impl YamlValueSeqAccess {
pub(crate) fn new(data: Vec<YamlValue>) -> Self {
// The Vec::pop() is much quicker than Vec::remove(0), so we
// reverse it.
let mut data = data;
data.reverse();
Self { data }
}
}

impl<'de> SeqAccess<'de> for YamlValueSeqAccess {
type Error = RmsdError;

fn next_element_seed<K>(
&mut self,
seed: K,
) -> Result<Option<K::Value>, Self::Error>
where
K: DeserializeSeed<'de>,
{
if let Some(value) = self.data.pop() {
seed.deserialize(&mut RmsdDeserializer { parsed: value })
.map(Some)
} else {
Ok(None)
}
}

fn size_hint(&self) -> Option<usize> {
Some(self.data.len())
}
}
24 changes: 17 additions & 7 deletions src/deserializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ use std::str::FromStr;
use serde::de::{Deserializer, Visitor};
use serde::Deserialize;

use crate::{RmsdError, YamlValue, YamlValueData, YamlValueMapAccess};
use crate::{
RmsdError, YamlValue, YamlValueData, YamlValueMapAccess, YamlValueSeqAccess,
};

#[derive(Debug, Default)]
pub struct RmsdDeserializer {
Expand Down Expand Up @@ -194,34 +196,42 @@ impl<'de> Deserializer<'de> for &mut RmsdDeserializer {
todo!()
}

fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
todo!()
if let YamlValueData::Sequence(v) = &self.parsed.data {
let access = YamlValueSeqAccess::new(v.to_vec());
visitor.visit_seq(access)
} else {
Err(RmsdError::unexpected_yaml_node_type(
format!("Expecting a sequence, got {}", self.parsed.data),
self.parsed.start,
))
}
}

fn deserialize_tuple<V>(
self,
_len: usize,
_visitor: V,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
todo!()
self.deserialize_seq(visitor)
}

fn deserialize_tuple_struct<V>(
self,
_name: &'static str,
_len: usize,
_visitor: V,
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: Visitor<'de>,
{
todo!()
self.deserialize_seq(visitor)
}

fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
Expand Down
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: Apache-2.0

mod array;
mod char_iter;
mod deserializer;
mod error;
Expand All @@ -11,9 +12,10 @@ mod token;
mod token_iter;
mod value;

pub(crate) use self::array::{get_array, YamlValueSeqAccess};
pub(crate) use self::char_iter::CharsIter;
pub(crate) use self::indent::process_indent;
pub(crate) use self::map::YamlValueMapAccess;
pub(crate) use self::map::{get_map, YamlValueMapAccess};
pub(crate) use self::scalar_str::{
read_double_quoted_str, read_single_quoted_str, read_unquoted_str,
};
Expand Down
90 changes: 85 additions & 5 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ use std::hash::{DefaultHasher, Hasher};
use indexmap::IndexMap;
use serde::de::{DeserializeSeed, MapAccess};

use crate::{RmsdDeserializer, RmsdError, RmsdPosition, YamlValue};
use crate::{
RmsdDeserializer, RmsdError, RmsdPosition, TokensIter, YamlTokenData,
YamlValue, YamlValueData,
};

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct YamlValueMap(IndexMap<YamlValue, YamlValue>);
Expand Down Expand Up @@ -38,6 +41,10 @@ impl YamlValueMap {
pub(crate) fn pop(&mut self) -> Option<(YamlValue, YamlValue)> {
self.0.pop()
}

pub(crate) fn len(&self) -> usize {
self.0.len()
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -78,8 +85,6 @@ impl<'de> MapAccess<'de> for YamlValueMapAccess {
return Ok(None);
};

println!("HAHA key {:?}", key);

seed.deserialize(&mut RmsdDeserializer { parsed: key })
.map(Some)
}
Expand All @@ -100,8 +105,83 @@ impl<'de> MapAccess<'de> for YamlValueMapAccess {
));
};

println!("HAHA val {:?}", value);

seed.deserialize(&mut RmsdDeserializer { parsed: value })
}

fn size_hint(&self) -> Option<usize> {
Some(self.data.len())
}
}

pub(crate) fn get_map(
iter: &mut TokensIter,
) -> Result<YamlValueMap, RmsdError> {
let mut ret = YamlValueMap::new();

let indent = if let Some(first_token) = iter.peek() {
first_token.indent
} else {
return Ok(ret);
};

let mut key: Option<YamlValue> = None;
while let Some(token) = iter.peek() {
if token.indent < indent {
return Ok(ret);
}

match &token.data {
YamlTokenData::Scalar(_) => {
if let Some(k) = key.take() {
if token.indent == indent {
// The unwrap is safe here as the `peek()` already check
// it is not None.
let token = iter.next().unwrap();
if let YamlTokenData::Scalar(s) = token.data {
let value = YamlValue {
data: YamlValueData::Scalar(s),
start: token.start,
end: token.end,
};
ret.insert(k, value);
} else {
unreachable!()
}
} else {
// The value is nested
let nested_tokens =
iter.remove_tokens_with_the_same_indent();
ret.insert(k, YamlValue::try_from(nested_tokens)?);
}
} else {
// The unwrap is safe here as the `peek()` already check
// it is not None.
let token = iter.next().unwrap();
if let YamlTokenData::Scalar(s) = token.data {
key = Some(YamlValue {
data: YamlValueData::Scalar(s),
start: token.start,
end: token.end,
});
} else {
unreachable!();
}
}
}
YamlTokenData::MapValueIndicator => {
if key.is_none() {
return Err(RmsdError::unexpected_yaml_node_type(
"Got map value indicator `:` with \
no key defined before"
.to_string(),
token.start,
));
}
iter.next();
}
// Support JSON format
_ => todo!(),
}
}
Ok(ret)
}
77 changes: 2 additions & 75 deletions src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
use std::str::FromStr;

use crate::{
RmsdError, RmsdPosition, TokensIter, YamlToken, YamlTokenData, YamlValueMap,
get_array, get_map, RmsdError, RmsdPosition, TokensIter, YamlToken,
YamlTokenData, YamlValueMap,
};

#[derive(Debug, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -219,80 +220,6 @@ fn get_container_type(tokens: &[YamlToken]) -> ContainerType {
}
}

fn get_map(iter: &mut TokensIter) -> Result<YamlValueMap, RmsdError> {
let mut ret = YamlValueMap::new();

let indent = if let Some(first_token) = iter.peek() {
first_token.indent
} else {
return Ok(ret);
};

let mut key: Option<YamlValue> = None;
while let Some(token) = iter.peek() {
if token.indent < indent {
return Ok(ret);
}

match &token.data {
YamlTokenData::Scalar(_) => {
if let Some(k) = key.take() {
if token.indent == indent {
// The unwrap is safe here as the `peek()` already check
// it is not None.
let token = iter.next().unwrap();
if let YamlTokenData::Scalar(s) = token.data {
let value = YamlValue {
data: YamlValueData::Scalar(s),
start: token.start,
end: token.end,
};
ret.insert(k, value);
} else {
unreachable!()
}
} else {
// The value is nested
let nested_tokens =
iter.remove_tokens_with_the_same_indent();
ret.insert(k, YamlValue::try_from(nested_tokens)?);
}
} else {
// The unwrap is safe here as the `peek()` already check
// it is not None.
let token = iter.next().unwrap();
if let YamlTokenData::Scalar(s) = token.data {
key = Some(YamlValue {
data: YamlValueData::Scalar(s),
start: token.start,
end: token.end,
});
} else {
unreachable!();
}
}
}
YamlTokenData::MapValueIndicator => {
if key.is_none() {
return Err(RmsdError::unexpected_yaml_node_type(
"Got map value indicator `:` with \
no key defined before"
.to_string(),
token.start,
));
}
iter.next();
}
_ => todo!(),
}
}
Ok(ret)
}

fn get_array(_iter: &mut TokensIter) -> Result<Vec<YamlValue>, RmsdError> {
todo!()
}

fn get_scalar(token: YamlToken) -> Result<YamlValueData, RmsdError> {
if let YamlTokenData::Scalar(s) = token.data {
Ok(YamlValueData::Scalar(s))
Expand Down
Loading

0 comments on commit 26b8f43

Please sign in to comment.