Skip to content

Commit

Permalink
refactor: extract consts
Browse files Browse the repository at this point in the history
  • Loading branch information
josecelano committed Sep 25, 2024
1 parent b3c0c8b commit 5f1e8ba
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 33 deletions.
48 changes: 25 additions & 23 deletions src/parsers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,13 @@ impl<R: Read, W: Write> BencodeParser<R, W> {
// Begin of list
self.begin_bencoded_value()?;
self.byte_writer.write_byte(b'[')?;
self.stack.push(State::ExpectingFirstItemOrEnd);
self.stack.push(State::ExpectingFirstListItemOrEnd);
}
b'd' => {
// Begin of dictionary
self.begin_bencoded_value()?;
self.byte_writer.write_byte(b'{')?;
self.stack.push(State::ExpectingFirstFieldOrEnd);
self.stack.push(State::ExpectingFirstDictFieldOrEnd);
}
b'e' => {
// End of list or dictionary (not end of integer)
Expand All @@ -104,6 +104,13 @@ impl<R: Read, W: Write> BencodeParser<R, W> {
Ok(())
}

/// JSON separator for items in a list
const LIST_ITEMS_SEPARATOR: u8 = b',';
/// JSON separator for field key and value in a object
const DICT_FIELD_KEY_VALUE_SEPARATOR: u8 = b':';
/// JSON separator for fields in a object
const DICT_FIELDS_SEPARATOR: u8 = b',';

/// It updates the stack state and prints the delimiters when needed.
///
/// Called when the first byt of a bencoded value (integer, string, list or dict)
Expand All @@ -114,29 +121,24 @@ impl<R: Read, W: Write> BencodeParser<R, W> {
/// Will return an error if the writer can't write to the output.
pub fn begin_bencoded_value(&mut self) -> io::Result<()> {
match self.stack.peek() {
// Initial state
State::Initial => {}
// List
State::ExpectingFirstItemOrEnd => {
self.stack.swap_top(State::ExpectingNextItem);
State::ExpectingFirstListItemOrEnd => {
self.stack.swap_top(State::ExpectingNextListItem);
}
State::ExpectingNextItem => {
// Items separator
self.byte_writer.write_byte(b',')?;
State::ExpectingNextListItem => {
self.byte_writer.write_byte(Self::LIST_ITEMS_SEPARATOR)?;
}
// Dictionary
State::ExpectingFirstFieldOrEnd => {
self.stack.swap_top(State::ExpectingFieldValue);
State::ExpectingFirstDictFieldOrEnd => {
self.stack.swap_top(State::ExpectingDictFieldValue);
}
State::ExpectingFieldValue => {
// Key/Value separator
self.byte_writer.write_byte(b':')?;
self.stack.swap_top(State::ExpectingFieldKey);
State::ExpectingDictFieldValue => {
self.byte_writer
.write_byte(Self::DICT_FIELD_KEY_VALUE_SEPARATOR)?;
self.stack.swap_top(State::ExpectingDictFieldKey);
}
State::ExpectingFieldKey => {
// Field separator
self.byte_writer.write_byte(b',')?;
self.stack.swap_top(State::ExpectingFieldValue);
State::ExpectingDictFieldKey => {
self.byte_writer.write_byte(Self::DICT_FIELDS_SEPARATOR)?;
self.stack.swap_top(State::ExpectingDictFieldValue);
}
}

Expand All @@ -158,14 +160,14 @@ impl<R: Read, W: Write> BencodeParser<R, W> {
/// expected.
pub fn end_bencoded_value(&mut self) -> io::Result<()> {
match self.stack.peek() {
State::ExpectingFirstItemOrEnd | State::ExpectingNextItem => {
State::ExpectingFirstListItemOrEnd | State::ExpectingNextListItem => {
self.byte_writer.write_byte(b']')?;
self.stack.pop();
}
State::ExpectingFirstFieldOrEnd | State::ExpectingFieldKey => {
State::ExpectingFirstDictFieldOrEnd | State::ExpectingDictFieldKey => {
self.byte_writer.write_byte(b'}')?;
}
State::ExpectingFieldValue | State::Initial => {
State::ExpectingDictFieldValue | State::Initial => {
// todo: pass the type of value (list or dict) to customize the error message
panic!("error parsing end of list or dictionary, unexpected initial state on the stack")
}
Expand Down
20 changes: 10 additions & 10 deletions src/parsers/stack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,24 @@ pub enum State {
Initial, // I

// States while parsing lists
ExpectingFirstItemOrEnd, // L
ExpectingNextItem, // M
ExpectingFirstListItemOrEnd, // L
ExpectingNextListItem, // M

// States while parsing dictionaries
ExpectingFirstFieldOrEnd, // D
ExpectingFieldValue, // E
ExpectingFieldKey, // F
ExpectingFirstDictFieldOrEnd, // D
ExpectingDictFieldValue, // E
ExpectingDictFieldKey, // F
}

impl Display for State {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let output = match self {
State::Initial => "I",
State::ExpectingFirstItemOrEnd => "L",
State::ExpectingNextItem => "M",
State::ExpectingFirstFieldOrEnd => "D",
State::ExpectingFieldValue => "E",
State::ExpectingFieldKey => "F",
State::ExpectingFirstListItemOrEnd => "L",
State::ExpectingNextListItem => "M",
State::ExpectingFirstDictFieldOrEnd => "D",
State::ExpectingDictFieldValue => "E",
State::ExpectingDictFieldKey => "F",
};
write!(f, "{output}")
}
Expand Down

0 comments on commit 5f1e8ba

Please sign in to comment.