mirror of
git://git.psyc.eu/libpsyc
synced 2024-08-15 03:19:02 +00:00
partial parsing possible with PsycParser and PsycListParser
This commit is contained in:
parent
6330086b77
commit
dd8cc059c5
6 changed files with 640 additions and 249 deletions
|
@ -64,17 +64,16 @@ pub struct PsycParser {
|
||||||
state: PsycParseState
|
state: PsycParseState
|
||||||
}
|
}
|
||||||
|
|
||||||
//pub struct PsycListParser<'a> {
|
pub struct PsycListParser {
|
||||||
// state: PsycParseListState,
|
state: PsycParseListState
|
||||||
// parsed_list: Vec<Vec<u8>>,
|
}
|
||||||
// buffer: &'a [u8]
|
|
||||||
//}
|
pub struct PsycDictParser<'a> {
|
||||||
//
|
state: PsycParseDictState,
|
||||||
//pub struct PsycDictParser<'a> {
|
parsed_key: Option<&'a [u8]>,
|
||||||
// state: PsycParseDictState,
|
buffer: Option<&'a [u8]>,
|
||||||
// parsed_key: Option<&'a [u8]>,
|
cursor: usize
|
||||||
// cursor: usize
|
}
|
||||||
//}
|
|
||||||
//
|
//
|
||||||
//// TODO: What data structures does the index parser need?
|
//// TODO: What data structures does the index parser need?
|
||||||
//pub struct PsycIndexParser {
|
//pub struct PsycIndexParser {
|
||||||
|
@ -129,24 +128,24 @@ pub enum PsycParserResult<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
//pub enum PsycListParserResult {
|
pub enum PsycListParserResult<'a> {
|
||||||
// Complete,
|
Complete,
|
||||||
// InsufficientData,
|
InsufficientData,
|
||||||
// ListElement {
|
ListElement {
|
||||||
// value: &[u8]
|
value: &'a [u8]
|
||||||
// },
|
},
|
||||||
// ListElementStart {
|
ListElementStart {
|
||||||
// value_part: &[u8]
|
value_part: &'a [u8]
|
||||||
// },
|
},
|
||||||
// ListElementCont {
|
ListElementCont {
|
||||||
// value_part: &[u8]
|
value_part: &'a [u8]
|
||||||
// },
|
},
|
||||||
// ListElementEnd {
|
ListElementEnd {
|
||||||
// value_part: &[u8]
|
value_part: &'a [u8]
|
||||||
// }
|
}
|
||||||
//}
|
}
|
||||||
//
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, PartialEq)]
|
||||||
pub enum PsycDictParserResult<'a> {
|
pub enum PsycDictParserResult<'a> {
|
||||||
Complete,
|
Complete,
|
||||||
|
@ -205,9 +204,10 @@ pub enum PsycDictParserError {
|
||||||
InvalidKeyStart = PsycParseDictRC::PSYC_PARSE_DICT_ERROR_KEY_START as _,
|
InvalidKeyStart = PsycParseDictRC::PSYC_PARSE_DICT_ERROR_KEY_START as _,
|
||||||
InvalidKeyType = PsycParseDictRC::PSYC_PARSE_DICT_ERROR_TYPE as _,
|
InvalidKeyType = PsycParseDictRC::PSYC_PARSE_DICT_ERROR_TYPE as _,
|
||||||
GenericError = PsycParseDictRC::PSYC_PARSE_DICT_ERROR as _,
|
GenericError = PsycParseDictRC::PSYC_PARSE_DICT_ERROR as _,
|
||||||
|
NoBuffer
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PsycParser {
|
impl<'a> PsycParser {
|
||||||
/// Create a PsycParser
|
/// Create a PsycParser
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let mut state: PsycParseState;
|
let mut state: PsycParseState;
|
||||||
|
@ -217,14 +217,13 @@ impl PsycParser {
|
||||||
psyc_parse_state_init(state_ptr, PsycParseFlag::PSYC_PARSE_ALL as u8)
|
psyc_parse_state_init(state_ptr, PsycParseFlag::PSYC_PARSE_ALL as u8)
|
||||||
}
|
}
|
||||||
PsycParser {
|
PsycParser {
|
||||||
state: state,
|
state: state
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse the buffer previously set by set_buffer. Call repeatedly until the
|
/// Parse the buffer previously set by set_buffer. Call repeatedly until the
|
||||||
/// result is PsycParserResult::Complete or a PsycParserError.
|
/// result is PsycParserResult::Complete or a PsycParserError.
|
||||||
pub fn parse<'a>(&mut self)
|
pub fn parse(&mut self) -> Result<PsycParserResult<'a>, PsycParserError> {
|
||||||
-> Result<PsycParserResult<'a>, PsycParserError> {
|
|
||||||
let state_ptr = &mut self.state as *mut PsycParseState;
|
let state_ptr = &mut self.state as *mut PsycParseState;
|
||||||
let mut operator = '\0';
|
let mut operator = '\0';
|
||||||
let mut name: PsycString;
|
let mut name: PsycString;
|
||||||
|
@ -325,8 +324,8 @@ impl PsycParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parser for PsycParser {
|
impl<'a> Parser<'a> for PsycParser {
|
||||||
fn set_buffer(&mut self, buffer: &[u8]) {
|
fn set_buffer(&mut self, buffer: &'a [u8]) {
|
||||||
let state_ptr = &mut self.state as *mut PsycParseState;
|
let state_ptr = &mut self.state as *mut PsycParseState;
|
||||||
let buffer_ptr = buffer.as_ptr() as *const c_char;
|
let buffer_ptr = buffer.as_ptr() as *const c_char;
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -347,100 +346,266 @@ impl Parser for PsycParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//impl<'a> PsycDictParser<'a> {
|
impl PsycListParser {
|
||||||
// /// Create a PsycDictParser
|
pub fn new() -> Self {
|
||||||
// pub fn new() -> Self {
|
let mut state: PsycParseListState;
|
||||||
// let mut state: PsycParseDictState;
|
unsafe {
|
||||||
// unsafe {
|
state = mem::uninitialized();
|
||||||
// state = mem::uninitialized();
|
let state_ptr = &mut state as *mut PsycParseListState;
|
||||||
// let state_ptr = &mut state as *mut PsycParseDictState;
|
psyc_parse_list_state_init(state_ptr)
|
||||||
// psyc_parse_dict_state_init(state_ptr)
|
}
|
||||||
// }
|
PsycListParser {
|
||||||
// PsycDictParser {
|
state: state
|
||||||
// state: state,
|
}
|
||||||
// parsed_key: None,
|
}
|
||||||
// parsed_dict: vec![],
|
|
||||||
// buffer: None,
|
|
||||||
// cursor: 0
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /// Set a buffer of raw bytes for parsing
|
|
||||||
// pub fn set_buffer(&mut self, buffer: &'a [u8]) {
|
|
||||||
// self.buffer = Some(buffer);
|
|
||||||
// let state_ptr = &mut self.state as *mut PsycParseDictState;
|
|
||||||
// let buffer_ptr = &buffer[self.cursor] as *const u8 as *const c_char;
|
|
||||||
// unsafe {
|
|
||||||
// psyc_parse_dict_buffer_set(state_ptr, buffer_ptr, buffer.len())
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// /// Parse the buffer previously set by set_buffer. Call repeatedly until the
|
|
||||||
// /// result is PsycDictParserResult::Complete or a PsycDictParserError
|
|
||||||
// pub fn parse(&mut self)
|
|
||||||
// -> Result<PsycDictParserResult<'a>, PsycDictParserError> {
|
|
||||||
// let state_ptr = &mut self.state as *mut PsycParseDictState;
|
|
||||||
// let mut list_type: PsycString;
|
|
||||||
// let mut element: PsycString;
|
|
||||||
// unsafe {
|
|
||||||
// list_type = mem::uninitialized();
|
|
||||||
// element = mem::uninitialized();
|
|
||||||
// let list_type_ptr = &mut list_type as *mut PsycString;
|
|
||||||
// let element_ptr = &mut element as *mut PsycString;
|
|
||||||
// loop {
|
|
||||||
// let parse_result = psyc_parse_dict(state_ptr, list_type_ptr, element_ptr);
|
|
||||||
// self.cursor = self.cursor + self.state.cursor;
|
|
||||||
// println!("parse_result: {:?}", parse_result);
|
|
||||||
// match parse_result {
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_KEY_END |
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_KEY => {
|
|
||||||
// let key = util::cstring_to_slice(element.data, element.length);
|
|
||||||
// self.parsed_key = Some(key)
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_VALUE_END |
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_VALUE => {
|
|
||||||
// let value = util::cstring_to_slice(element.data, element.length);
|
|
||||||
// self.parsed_dict.push((self.parsed_key.unwrap(), value))
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_VALUE_LAST => {
|
|
||||||
// let value = util::cstring_to_slice(element.data, element.length);
|
|
||||||
// self.parsed_dict.push((self.parsed_key.unwrap(), value));
|
|
||||||
// let complete = PsycDictParserResult::Complete {
|
|
||||||
// dict: self.parsed_dict.clone()
|
|
||||||
// };
|
|
||||||
// return Ok(complete);
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_INSUFFICIENT |
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_KEY_START |
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_KEY_CONT |
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_VALUE_START |
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_VALUE_CONT |
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_END /* FIXME: correct? */=> {
|
|
||||||
// return Ok(PsycDictParserResult::InsufficientData);
|
|
||||||
// },
|
|
||||||
//
|
|
||||||
// PsycParseDictRC::PSYC_PARSE_DICT_TYPE => (),
|
|
||||||
//
|
|
||||||
// _error => {
|
|
||||||
// return Err(mem::transmute(_error));
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
pub trait Parser {
|
pub fn parse<'a>(&mut self) -> Result<PsycListParserResult<'a>, PsycListParserError> {
|
||||||
|
let state_ptr = &mut self.state as *mut PsycParseListState;
|
||||||
|
let mut list_type: PsycString;
|
||||||
|
let mut element: PsycString;
|
||||||
|
unsafe {
|
||||||
|
list_type = mem::uninitialized();
|
||||||
|
element = mem::uninitialized();
|
||||||
|
let list_type_ptr = &mut list_type as *mut PsycString;
|
||||||
|
let element_ptr = &mut element as *mut PsycString;
|
||||||
|
loop {
|
||||||
|
let parse_result = psyc_parse_list(state_ptr, list_type_ptr, element_ptr);
|
||||||
|
println!("parse_result: {:?}", parse_result);
|
||||||
|
println!("cursor: {}", self.state.cursor);
|
||||||
|
match parse_result {
|
||||||
|
PsycParseListRC::PSYC_PARSE_LIST_END =>
|
||||||
|
return Ok(PsycListParserResult::Complete),
|
||||||
|
|
||||||
|
PsycParseListRC::PSYC_PARSE_LIST_INSUFFICIENT =>
|
||||||
|
return Ok(PsycListParserResult::InsufficientData),
|
||||||
|
|
||||||
|
PsycParseListRC::PSYC_PARSE_LIST_ELEM_LAST |
|
||||||
|
PsycParseListRC::PSYC_PARSE_LIST_ELEM => {
|
||||||
|
let result = PsycListParserResult::ListElement {
|
||||||
|
value: util::cstring_to_slice(element.data, element.length)
|
||||||
|
};
|
||||||
|
return Ok(result)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseListRC::PSYC_PARSE_LIST_ELEM_START => {
|
||||||
|
let result = PsycListParserResult::ListElementStart {
|
||||||
|
value_part: util::cstring_to_slice(element.data, element.length)
|
||||||
|
};
|
||||||
|
return Ok(result)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseListRC::PSYC_PARSE_LIST_ELEM_CONT => {
|
||||||
|
let result = PsycListParserResult::ListElementCont {
|
||||||
|
value_part: util::cstring_to_slice(element.data, element.length)
|
||||||
|
};
|
||||||
|
return Ok(result)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseListRC::PSYC_PARSE_LIST_ELEM_END => {
|
||||||
|
let result = PsycListParserResult::ListElementEnd {
|
||||||
|
value_part: util::cstring_to_slice(element.data, element.length)
|
||||||
|
};
|
||||||
|
return Ok(result)
|
||||||
|
},
|
||||||
|
|
||||||
|
//PsycParseListRC::PSYC_PARSE_LIST_ELEM_LAST => {
|
||||||
|
// let result: PsycListParserResult;
|
||||||
|
// if ! self.finished {
|
||||||
|
// result = PsycListParserResult::ListElement {
|
||||||
|
// value: util::cstring_to_slice(element.data, element.length)
|
||||||
|
// };
|
||||||
|
// self.finished = true
|
||||||
|
// } else {
|
||||||
|
// result = PsycListParserResult::Complete
|
||||||
|
// }
|
||||||
|
// return Ok(result)
|
||||||
|
//},
|
||||||
|
|
||||||
|
PsycParseListRC::PSYC_PARSE_LIST_TYPE => (),
|
||||||
|
|
||||||
|
_error => {
|
||||||
|
return Err(mem::transmute(_error))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parser<'a> for PsycListParser {
|
||||||
|
fn set_buffer(&mut self, buffer: &'a [u8]) {
|
||||||
|
let state_ptr = &mut self.state as *mut PsycParseListState;
|
||||||
|
let buffer_ptr = buffer.as_ptr() as *const c_char;
|
||||||
|
unsafe {
|
||||||
|
psyc_parse_list_buffer_set(state_ptr, buffer_ptr, buffer.len())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unparsed_position(&self) -> usize {
|
||||||
|
self.state.cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unparsed_length(&self) -> usize {
|
||||||
|
self.state.buffer.length - self.state.cursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> PsycDictParser<'a> {
|
||||||
|
/// Create a PsycDictParser
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let mut state: PsycParseDictState;
|
||||||
|
unsafe {
|
||||||
|
state = mem::uninitialized();
|
||||||
|
let state_ptr = &mut state as *mut PsycParseDictState;
|
||||||
|
psyc_parse_dict_state_init(state_ptr)
|
||||||
|
}
|
||||||
|
PsycDictParser {
|
||||||
|
state: state,
|
||||||
|
parsed_key: None,
|
||||||
|
buffer: None,
|
||||||
|
cursor: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Parse the buffer previously set by set_buffer. Call repeatedly until the
|
||||||
|
/// result is PsycDictParserResult::Complete or a PsycDictParserError
|
||||||
|
pub fn parse(&mut self)
|
||||||
|
-> Result<PsycDictParserResult<'a>, PsycDictParserError> {
|
||||||
|
if self.buffer == None {
|
||||||
|
return Err(PsycDictParserError::NoBuffer)
|
||||||
|
}
|
||||||
|
if self.buffer.unwrap().is_empty() {
|
||||||
|
return Ok(PsycDictParserResult::Complete);
|
||||||
|
}
|
||||||
|
let state_ptr = &mut self.state as *mut PsycParseDictState;
|
||||||
|
let mut list_type: PsycString;
|
||||||
|
let mut element: PsycString;
|
||||||
|
unsafe {
|
||||||
|
list_type = mem::uninitialized();
|
||||||
|
element = mem::uninitialized();
|
||||||
|
let list_type_ptr = &mut list_type as *mut PsycString;
|
||||||
|
let element_ptr = &mut element as *mut PsycString;
|
||||||
|
loop {
|
||||||
|
let parse_result = psyc_parse_dict(state_ptr, list_type_ptr, element_ptr);
|
||||||
|
println!("parse_result: {:?}", parse_result);
|
||||||
|
println!("cursor: {}", self.state.cursor);
|
||||||
|
self.cursor = self.state.cursor;
|
||||||
|
match parse_result {
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_END =>
|
||||||
|
return Ok(PsycDictParserResult::Complete),
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_INSUFFICIENT =>
|
||||||
|
return Ok(PsycDictParserResult::InsufficientData),
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_KEY => {
|
||||||
|
let key = util::cstring_to_slice(element.data, element.length);
|
||||||
|
self.parsed_key = Some(key)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_KEY_START => {
|
||||||
|
self.cursor = element.data as usize -
|
||||||
|
self.buffer.unwrap().as_ptr() as usize;
|
||||||
|
return Ok(PsycDictParserResult::InsufficientData)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_KEY_CONT => {
|
||||||
|
return Ok(PsycDictParserResult::InsufficientData)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_KEY_END => {
|
||||||
|
let end_index = self.cursor + element.length;
|
||||||
|
let key = &self.buffer.unwrap()[self.cursor .. end_index];
|
||||||
|
self.parsed_key = Some(key)
|
||||||
|
},
|
||||||
|
|
||||||
|
//PsycParseDictRC::PSYC_PARSE_DICT_VALUE => {
|
||||||
|
// let result = PsycDictParserResult::DictEntry {
|
||||||
|
// key: self.parsed_key.unwrap(),
|
||||||
|
// value: util::cstring_to_slice(element.data, element.length)
|
||||||
|
// };
|
||||||
|
// return Ok(result)
|
||||||
|
//},
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_VALUE |
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_VALUE_LAST => {
|
||||||
|
//let result: PsycDictParserResult;
|
||||||
|
//// FIXME: workaround
|
||||||
|
//if ! self.finished {
|
||||||
|
// result = PsycDictParserResult::DictEntry {
|
||||||
|
// key: self.parsed_key.unwrap(),
|
||||||
|
// value: util::cstring_to_slice(element.data, element.length)
|
||||||
|
// };
|
||||||
|
// self.finished = true
|
||||||
|
//} else {
|
||||||
|
// result = PsycDictParserResult::Complete;
|
||||||
|
//}
|
||||||
|
let result = PsycDictParserResult::DictEntry {
|
||||||
|
key: self.parsed_key.unwrap(),
|
||||||
|
value: util::cstring_to_slice(element.data, element.length)
|
||||||
|
};
|
||||||
|
return Ok(result)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_VALUE_START => {
|
||||||
|
let result = PsycDictParserResult::DictEntryStart {
|
||||||
|
key: self.parsed_key.unwrap(),
|
||||||
|
value_part: util::cstring_to_slice(element.data, element.length)
|
||||||
|
};
|
||||||
|
return Ok(result)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_VALUE_CONT => {
|
||||||
|
let result = PsycDictParserResult::DictEntryCont {
|
||||||
|
value_part: util::cstring_to_slice(element.data, element.length)
|
||||||
|
};
|
||||||
|
return Ok(result)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_VALUE_END => {
|
||||||
|
let result = PsycDictParserResult::DictEntryEnd {
|
||||||
|
value_part: util::cstring_to_slice(element.data, element.length)
|
||||||
|
};
|
||||||
|
return Ok(result)
|
||||||
|
},
|
||||||
|
|
||||||
|
PsycParseDictRC::PSYC_PARSE_DICT_TYPE => (),
|
||||||
|
|
||||||
|
_error => {
|
||||||
|
return Err(mem::transmute(_error))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Parser<'a> for PsycDictParser<'a> {
|
||||||
|
fn set_buffer(&mut self, buffer: &'a [u8]) {
|
||||||
|
self.buffer = Some(buffer);
|
||||||
|
let state_ptr = &mut self.state as *mut PsycParseDictState;
|
||||||
|
let buffer_ptr = buffer.as_ptr() as *const c_char;
|
||||||
|
unsafe {
|
||||||
|
psyc_parse_dict_buffer_set(state_ptr, buffer_ptr, buffer.len());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unparsed_position(&self) -> usize {
|
||||||
|
self.cursor
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unparsed_length(&self) -> usize {
|
||||||
|
self.state.buffer.length - self.cursor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Parser<'a> {
|
||||||
/// Set a buffer of raw bytes for parsing
|
/// Set a buffer of raw bytes for parsing
|
||||||
fn set_buffer(&mut self, buffer: &[u8]);
|
fn set_buffer(&mut self, buffer: &'a [u8]);
|
||||||
|
|
||||||
/// copies the remaining unparsed bytes to the beginning of the given buffer.
|
/// copies the remaining unparsed bytes to the beginning of the given buffer.
|
||||||
/// Returns the number of copied bytes. Must be called when parse() returned
|
/// Returns the number of copied bytes. Must be called when parse() returned
|
||||||
/// InsufficientData as Result.
|
/// InsufficientData as Result.
|
||||||
fn copy_unparsed_into_buffer(&self, buffer: &mut [u8]) -> usize {
|
fn copy_unparsed_into_buffer(&self, buffer: &'a mut [u8]) -> usize {
|
||||||
let unparsed_pos = self.unparsed_position();
|
let unparsed_pos = self.unparsed_position();
|
||||||
let unparsed_len = self.unparsed_length();
|
let unparsed_len = self.unparsed_length();
|
||||||
if unparsed_pos != 0 {
|
if unparsed_pos != 0 {
|
||||||
|
|
|
@ -25,7 +25,7 @@ pub struct PsycParseState {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct PsycParseListState {
|
pub struct PsycParseListState {
|
||||||
buffer: PsycString,
|
pub buffer: PsycString,
|
||||||
pub cursor: usize,
|
pub cursor: usize,
|
||||||
startc: usize,
|
startc: usize,
|
||||||
list_type: PsycString,
|
list_type: PsycString,
|
||||||
|
@ -37,7 +37,7 @@ pub struct PsycParseListState {
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub struct PsycParseDictState {
|
pub struct PsycParseDictState {
|
||||||
buffer: PsycString,
|
pub buffer: PsycString,
|
||||||
pub cursor: usize,
|
pub cursor: usize,
|
||||||
startc: usize,
|
startc: usize,
|
||||||
elemlen: usize,
|
elemlen: usize,
|
||||||
|
@ -151,6 +151,7 @@ pub enum PsycParseRC {
|
||||||
PSYC_PARSE_COMPLETE = 13,
|
PSYC_PARSE_COMPLETE = 13,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
pub enum PsycParseListRC {
|
pub enum PsycParseListRC {
|
||||||
/// Error, no length is set for an element which is longer than PSYC_ELEM_SIZE_THRESHOLD.
|
/// Error, no length is set for an element which is longer than PSYC_ELEM_SIZE_THRESHOLD.
|
||||||
|
|
90
rust/tests/test_dict_parser.rs
Normal file
90
rust/tests/test_dict_parser.rs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
extern crate psyc;
|
||||||
|
use psyc::parser::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse() {
|
||||||
|
let test_data = "{foo1} bar1{foo2} bar2".to_string().into_bytes();
|
||||||
|
|
||||||
|
let expected1 = PsycDictParserResult::DictEntry{
|
||||||
|
key: b"foo1",
|
||||||
|
value: b"bar1"
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected2 = PsycDictParserResult::DictEntry{
|
||||||
|
key: b"foo2",
|
||||||
|
value: b"bar2"
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected3 = PsycDictParserResult::Complete;
|
||||||
|
|
||||||
|
let mut parser = PsycDictParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data);
|
||||||
|
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected1);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected2);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected3);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty() {
|
||||||
|
let test_data = "".to_string().into_bytes();
|
||||||
|
|
||||||
|
let mut parser = PsycDictParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data);
|
||||||
|
|
||||||
|
assert_eq!(parser.parse().unwrap(), PsycDictParserResult::Complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_incomplete() {
|
||||||
|
let test_data1 = "{foo1}4 bar".to_string().into_bytes();
|
||||||
|
let test_data2 = "1{foo2} bar2".to_string().into_bytes();
|
||||||
|
|
||||||
|
let expected = vec![PsycDictParserResult::DictEntryStart {
|
||||||
|
key: b"foo1",
|
||||||
|
value_part: b"bar"
|
||||||
|
},
|
||||||
|
PsycDictParserResult::DictEntryEnd {
|
||||||
|
value_part: b"1"
|
||||||
|
},
|
||||||
|
PsycDictParserResult::DictEntry {
|
||||||
|
key: b"foo2",
|
||||||
|
value: b"bar2"
|
||||||
|
}];
|
||||||
|
|
||||||
|
let mut parser = PsycDictParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data1);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[0]);
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data2);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[1]);
|
||||||
|
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
//#[test]
|
||||||
|
//fn test_insufficient() {
|
||||||
|
// let mut test_data1 = "{4 foo".to_string().into_bytes();
|
||||||
|
// let mut test_data2 = "1} bar1".to_string().into_bytes();
|
||||||
|
// let mut test_data3 = "{4 foo1} bar1".to_string().into_bytes();
|
||||||
|
//
|
||||||
|
// let expected = vec![PsycDictParserResult::InsufficientData,
|
||||||
|
// PsycDictParserResult::DictEntry {
|
||||||
|
// key: b"foo1",
|
||||||
|
// value: b"bar1"
|
||||||
|
// }];
|
||||||
|
//
|
||||||
|
// let mut parser = PsycDictParser::new();
|
||||||
|
//
|
||||||
|
// parser.set_buffer(&test_data1);
|
||||||
|
// assert_eq!(parser.parse().unwrap(), expected[0]);
|
||||||
|
//
|
||||||
|
// //let unparsed_length = parser.copy_unparsed_into_buffer(&mut test_data1);
|
||||||
|
// //test_data1.resize(unparsed_length, 0);
|
||||||
|
// //test_data1.append(&mut test_data2);
|
||||||
|
// parser.set_buffer(&test_data3);
|
||||||
|
// assert_eq!(parser.parse().unwrap(), expected[1]);
|
||||||
|
//}
|
90
rust/tests/test_list_parser.rs
Normal file
90
rust/tests/test_list_parser.rs
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
extern crate psyc;
|
||||||
|
use psyc::parser::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_parse() {
|
||||||
|
let test_data = "| element1| element2| element3".to_string().into_bytes();
|
||||||
|
|
||||||
|
let expected1 = PsycListParserResult::ListElement {
|
||||||
|
value: b"element1"
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected2 = PsycListParserResult::ListElement {
|
||||||
|
value: b"element2"
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected3 = PsycListParserResult::ListElement {
|
||||||
|
value: b"element3"
|
||||||
|
};
|
||||||
|
|
||||||
|
let expected4 = PsycListParserResult::Complete;
|
||||||
|
|
||||||
|
let mut parser = PsycListParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data);
|
||||||
|
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected1);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected2);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected3);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected4);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty() {
|
||||||
|
let test_data = "".to_string().into_bytes();
|
||||||
|
|
||||||
|
let mut parser = PsycListParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data);
|
||||||
|
|
||||||
|
assert_eq!(parser.parse().unwrap(), PsycListParserResult::Complete);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_incomplete() {
|
||||||
|
let test_data1 = "|8 element".to_string().into_bytes();
|
||||||
|
let test_data2 = "1| element2|".to_string().into_bytes();
|
||||||
|
|
||||||
|
let expected = vec![PsycListParserResult::ListElementStart {
|
||||||
|
value_part: b"element"
|
||||||
|
},
|
||||||
|
PsycListParserResult::ListElementEnd {
|
||||||
|
value_part: b"1"
|
||||||
|
},
|
||||||
|
PsycListParserResult::ListElement {
|
||||||
|
value: b"element2"
|
||||||
|
}];
|
||||||
|
|
||||||
|
let mut parser = PsycListParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data1);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[0]);
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data2);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[1]);
|
||||||
|
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_insufficient() {
|
||||||
|
let mut test_data1 = "|4".to_string().into_bytes();
|
||||||
|
let mut test_data2 = " foo1".to_string().into_bytes();
|
||||||
|
|
||||||
|
let expected = vec![PsycListParserResult::InsufficientData,
|
||||||
|
PsycListParserResult::ListElement {
|
||||||
|
value: b"foo1"
|
||||||
|
}];
|
||||||
|
|
||||||
|
let mut parser = PsycListParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data1);
|
||||||
|
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[0]);
|
||||||
|
|
||||||
|
let unparsed_length = parser.copy_unparsed_into_buffer(&mut test_data1);
|
||||||
|
test_data1.resize(unparsed_length, 0);
|
||||||
|
test_data1.append(&mut test_data2);
|
||||||
|
parser.set_buffer(&test_data1);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[1]);
|
||||||
|
}
|
|
@ -21,6 +21,43 @@ fn test_parse() {
|
||||||
assert_eq!(parser.parse().unwrap(), expected[1]);
|
assert_eq!(parser.parse().unwrap(), expected[1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_empty() {
|
||||||
|
let test_data = "".to_string().into_bytes();
|
||||||
|
|
||||||
|
let mut parser = PsycParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data);
|
||||||
|
|
||||||
|
// FIXME: InsufficientData or Complete?
|
||||||
|
assert_eq!(parser.parse().unwrap(), PsycParserResult::InsufficientData);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_incomplete() {
|
||||||
|
let test_data1 = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_nick 6\t".to_string().into_bytes();
|
||||||
|
|
||||||
|
let test_data2 = "lurchi".to_string().into_bytes();
|
||||||
|
|
||||||
|
let expected = vec![PsycParserResult::EntityModifierStart {
|
||||||
|
operator: ':',
|
||||||
|
name: b"_nick",
|
||||||
|
value_part: b""
|
||||||
|
},
|
||||||
|
PsycParserResult::EntityModifierEnd {
|
||||||
|
value_part: b"lurchi"
|
||||||
|
}];
|
||||||
|
|
||||||
|
let mut parser = PsycParser::new();
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data1);
|
||||||
|
let _ = parser.parse();
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[0]);
|
||||||
|
|
||||||
|
parser.set_buffer(&test_data2);
|
||||||
|
assert_eq!(parser.parse().unwrap(), expected[1]);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_insufficient() {
|
fn test_insufficient() {
|
||||||
let mut test_data1 = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_nick".to_string().into_bytes();
|
let mut test_data1 = ":_target\tpsyc://ve.symlynx.com/@blog\n\n:_nick".to_string().into_bytes();
|
||||||
|
|
14
src/parse.c
14
src/parse.c
|
@ -573,8 +573,9 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
||||||
{
|
{
|
||||||
ParseRC ret;
|
ParseRC ret;
|
||||||
|
|
||||||
if (state->cursor >= state->buffer.length)
|
if (state->cursor >= state->buffer.length) {
|
||||||
return PSYC_PARSE_LIST_END;
|
return PSYC_PARSE_LIST_END;
|
||||||
|
}
|
||||||
|
|
||||||
state->startc = state->cursor;
|
state->startc = state->cursor;
|
||||||
|
|
||||||
|
@ -639,6 +640,7 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PARSE_INSUFFICIENT: // end of buffer
|
case PARSE_INSUFFICIENT: // end of buffer
|
||||||
|
state->cursor = state->buffer.length;
|
||||||
return PSYC_PARSE_LIST_ELEM_LAST;
|
return PSYC_PARSE_LIST_ELEM_LAST;
|
||||||
case PARSE_ERROR:
|
case PARSE_ERROR:
|
||||||
return PSYC_PARSE_LIST_ERROR_ELEM_TYPE;
|
return PSYC_PARSE_LIST_ERROR_ELEM_TYPE;
|
||||||
|
@ -683,12 +685,14 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
||||||
switch (parse_binary((ParseState*)state, state->elemlen, elem,
|
switch (parse_binary((ParseState*)state, state->elemlen, elem,
|
||||||
&state->elem_parsed)) {
|
&state->elem_parsed)) {
|
||||||
case PARSE_SUCCESS:
|
case PARSE_SUCCESS:
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_START;
|
||||||
if (elem->length == state->elem_parsed)
|
if (elem->length == state->elem_parsed)
|
||||||
ret = PSYC_PARSE_LIST_ELEM;
|
ret = PSYC_PARSE_LIST_ELEM;
|
||||||
else
|
else
|
||||||
ret = PSYC_PARSE_LIST_ELEM_END;
|
ret = PSYC_PARSE_LIST_ELEM_END;
|
||||||
break;
|
break;
|
||||||
case PARSE_INCOMPLETE:
|
case PARSE_INCOMPLETE:
|
||||||
|
state->part = PSYC_LIST_PART_ELEM;
|
||||||
if (elem->length == state->elem_parsed)
|
if (elem->length == state->elem_parsed)
|
||||||
ret = PSYC_PARSE_LIST_ELEM_START;
|
ret = PSYC_PARSE_LIST_ELEM_START;
|
||||||
else
|
else
|
||||||
|
@ -700,16 +704,17 @@ psyc_parse_list (PsycParseListState *state, PsycString *type, PsycString *elem)
|
||||||
} else {
|
} else {
|
||||||
switch (parse_until((ParseState*)state, '|', elem)) {
|
switch (parse_until((ParseState*)state, '|', elem)) {
|
||||||
case PARSE_SUCCESS:
|
case PARSE_SUCCESS:
|
||||||
|
state->part = PSYC_LIST_PART_ELEM_START;
|
||||||
ret = PSYC_PARSE_LIST_ELEM;
|
ret = PSYC_PARSE_LIST_ELEM;
|
||||||
break;
|
break;
|
||||||
case PARSE_INSUFFICIENT:
|
case PARSE_INSUFFICIENT:
|
||||||
|
state->cursor = state->buffer.length;
|
||||||
return PSYC_PARSE_LIST_ELEM_LAST;
|
return PSYC_PARSE_LIST_ELEM_LAST;
|
||||||
default: // should not be reached
|
default: // should not be reached
|
||||||
return PSYC_PARSE_LIST_ERROR;
|
return PSYC_PARSE_LIST_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state->part = PSYC_LIST_PART_ELEM_START;
|
|
||||||
state->startc = state->cursor;
|
state->startc = state->cursor;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -873,6 +878,7 @@ psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PARSE_INSUFFICIENT: // end of buffer
|
case PARSE_INSUFFICIENT: // end of buffer
|
||||||
|
//state->cursor = state->buffer.length;
|
||||||
return PSYC_PARSE_DICT_VALUE_LAST;
|
return PSYC_PARSE_DICT_VALUE_LAST;
|
||||||
case PARSE_ERROR:
|
case PARSE_ERROR:
|
||||||
return PSYC_PARSE_DICT_ERROR_VALUE_TYPE;
|
return PSYC_PARSE_DICT_ERROR_VALUE_TYPE;
|
||||||
|
@ -917,6 +923,7 @@ psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem)
|
||||||
switch (parse_binary((ParseState*)state, state->elemlen, elem,
|
switch (parse_binary((ParseState*)state, state->elemlen, elem,
|
||||||
&state->elem_parsed)) {
|
&state->elem_parsed)) {
|
||||||
case PARSE_SUCCESS:
|
case PARSE_SUCCESS:
|
||||||
|
state->part = PSYC_DICT_PART_KEY_START;
|
||||||
if (elem->length == state->elem_parsed)
|
if (elem->length == state->elem_parsed)
|
||||||
ret = PSYC_PARSE_DICT_VALUE;
|
ret = PSYC_PARSE_DICT_VALUE;
|
||||||
else
|
else
|
||||||
|
@ -934,16 +941,17 @@ psyc_parse_dict (PsycParseDictState *state, PsycString *type, PsycString *elem)
|
||||||
} else {
|
} else {
|
||||||
switch (parse_until((ParseState*)state, '{', elem)) {
|
switch (parse_until((ParseState*)state, '{', elem)) {
|
||||||
case PARSE_SUCCESS:
|
case PARSE_SUCCESS:
|
||||||
|
state->part = PSYC_DICT_PART_KEY_START;
|
||||||
ret = PSYC_PARSE_DICT_VALUE;
|
ret = PSYC_PARSE_DICT_VALUE;
|
||||||
break;
|
break;
|
||||||
case PARSE_INSUFFICIENT:
|
case PARSE_INSUFFICIENT:
|
||||||
|
state->cursor = state->buffer.length;
|
||||||
return PSYC_PARSE_DICT_VALUE_LAST;
|
return PSYC_PARSE_DICT_VALUE_LAST;
|
||||||
default: // should not be reached
|
default: // should not be reached
|
||||||
return PSYC_PARSE_DICT_ERROR;
|
return PSYC_PARSE_DICT_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
state->part = PSYC_DICT_PART_KEY_START;
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue