Compare commits
2 Commits
876fbe15dc
...
7556471090
Author | SHA1 | Date | |
---|---|---|---|
7556471090 | |||
18c7eb9e81 |
@ -1,4 +1,48 @@
|
|||||||
pub mod custom;
|
pub mod custom;
|
||||||
pub mod de;
|
pub mod de;
|
||||||
pub mod ser;
|
pub mod ser;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use crate::bencode::de::from_bytes;
|
||||||
|
use crate::bencode::ser::to_bytes;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_roundtrip() {
|
||||||
|
#[derive(Serialize, Deserialize, PartialEq, Debug)]
|
||||||
|
struct A {
|
||||||
|
l: Vec<String>,
|
||||||
|
li: Vec<i32>,
|
||||||
|
m: HashMap<String, String>,
|
||||||
|
b: Vec<[u8; 4]>
|
||||||
|
}
|
||||||
|
|
||||||
|
let a = A {
|
||||||
|
l: vec!["foo".to_string(), "bar".to_string(), "".to_string(), "💩".to_string()],
|
||||||
|
li: vec![18, 7, 26, 8, 9],
|
||||||
|
m: HashMap::from([
|
||||||
|
("foo".to_string(), "bar".to_string()),
|
||||||
|
("💩".to_string(), "🤷♂️".to_string()),
|
||||||
|
("18".to_string(), "asdf".to_string())
|
||||||
|
]),
|
||||||
|
b: vec![
|
||||||
|
[4, 26, 7, 18],
|
||||||
|
[24, 13, 12, 4],
|
||||||
|
[8, 9, 10, 11]
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
let ser = to_bytes(&a).unwrap();
|
||||||
|
|
||||||
|
let de = from_bytes(&ser).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(a, de);
|
||||||
|
|
||||||
|
let ser2 = to_bytes(&de).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(ser, ser2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,14 +4,39 @@ use serde::{ser, Serialize};
|
|||||||
|
|
||||||
use crate::bencode::error::{Error, Result};
|
use crate::bencode::error::{Error, Result};
|
||||||
|
|
||||||
|
#[derive(PartialEq)]
|
||||||
|
enum TupleState {
|
||||||
|
None,
|
||||||
|
Unknown,
|
||||||
|
List,
|
||||||
|
ByteString,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Serializer {
|
pub struct Serializer {
|
||||||
output: Vec<u8>,
|
output: Vec<u8>,
|
||||||
|
tuple_state: TupleState,
|
||||||
|
tuple_len: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serializer {
|
impl Serializer {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
Serializer {
|
Serializer {
|
||||||
output: Vec::new(),
|
output: Vec::new(),
|
||||||
|
tuple_state: TupleState::None,
|
||||||
|
tuple_len: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_tuple_start_bytes(&mut self) {
|
||||||
|
if self.tuple_state == TupleState::Unknown {
|
||||||
|
self.tuple_state = TupleState::ByteString;
|
||||||
|
self.output.extend(format!("{}:", self.tuple_len).into_bytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn write_tuple_start_list(&mut self) {
|
||||||
|
if self.tuple_state == TupleState::Unknown {
|
||||||
|
self.tuple_state = TupleState::List;
|
||||||
|
self.output.push('l' as u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -54,37 +79,47 @@ impl<'a> ser::Serializer for &'a mut Serializer
|
|||||||
type SerializeStruct = MapSerializer<'a>;
|
type SerializeStruct = MapSerializer<'a>;
|
||||||
type SerializeStructVariant = Self;
|
type SerializeStructVariant = Self;
|
||||||
|
|
||||||
fn serialize_bool(self, v: bool) -> Result<()> {
|
fn serialize_bool(self, _v: bool) -> Result<()> {
|
||||||
Err(Error::WontImplement)
|
Err(Error::WontImplement)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i8(self, v: i8) -> Result<()> {
|
fn serialize_i8(self, v: i8) -> Result<()> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.extend(format!("i{v}e").into_bytes());
|
self.output.extend(format!("i{v}e").into_bytes());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i16(self, v: i16) -> Result<()> {
|
fn serialize_i16(self, v: i16) -> Result<()> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.extend(format!("i{v}e").into_bytes());
|
self.output.extend(format!("i{v}e").into_bytes());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i32(self, v: i32) -> Result<()> {
|
fn serialize_i32(self, v: i32) -> Result<()> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.extend(format!("i{v}e").into_bytes());
|
self.output.extend(format!("i{v}e").into_bytes());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i64(self, v: i64) -> Result<()> {
|
fn serialize_i64(self, v: i64) -> Result<()> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.extend(format!("i{v}e").into_bytes());
|
self.output.extend(format!("i{v}e").into_bytes());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_i128(self, v: i128) -> Result<()> {
|
fn serialize_i128(self, v: i128) -> Result<()> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.extend(format!("i{v}e").into_bytes());
|
self.output.extend(format!("i{v}e").into_bytes());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_u8(self, v: u8) -> Result<()> {
|
fn serialize_u8(self, v: u8) -> Result<()> {
|
||||||
todo!()
|
if self.tuple_state == TupleState::None {
|
||||||
|
return Err(Error::WontImplement);
|
||||||
|
}
|
||||||
|
self.write_tuple_start_bytes();
|
||||||
|
self.output.push(v);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_u16(self, _v: u16) -> Result<()> {
|
fn serialize_u16(self, _v: u16) -> Result<()> {
|
||||||
@ -112,6 +147,7 @@ impl<'a> ser::Serializer for &'a mut Serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_char(self, v: char) -> Result<()> {
|
fn serialize_char(self, v: char) -> Result<()> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.extend(format!("{}:", v.len_utf8()).into_bytes());
|
self.output.extend(format!("{}:", v.len_utf8()).into_bytes());
|
||||||
let mut b = [0; 4];
|
let mut b = [0; 4];
|
||||||
v.encode_utf8(&mut b);
|
v.encode_utf8(&mut b);
|
||||||
@ -120,12 +156,14 @@ impl<'a> ser::Serializer for &'a mut Serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_str(self, v: &str) -> Result<()> {
|
fn serialize_str(self, v: &str) -> Result<()> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.extend(format!("{}:", v.len()).into_bytes());
|
self.output.extend(format!("{}:", v.len()).into_bytes());
|
||||||
self.output.extend(v.as_bytes());
|
self.output.extend(v.as_bytes());
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
|
fn serialize_bytes(self, v: &[u8]) -> Result<()> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.extend(format!("{}:", v.len()).into_bytes());
|
self.output.extend(format!("{}:", v.len()).into_bytes());
|
||||||
self.output.extend(v);
|
self.output.extend(v);
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -139,6 +177,7 @@ impl<'a> ser::Serializer for &'a mut Serializer
|
|||||||
where
|
where
|
||||||
T: ?Sized + Serialize
|
T: ?Sized + Serialize
|
||||||
{
|
{
|
||||||
|
self.write_tuple_start_list();
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,10 +197,11 @@ impl<'a> ser::Serializer for &'a mut Serializer
|
|||||||
where
|
where
|
||||||
T: ?Sized + Serialize
|
T: ?Sized + Serialize
|
||||||
{
|
{
|
||||||
|
self.write_tuple_start_list();
|
||||||
value.serialize(self)
|
value.serialize(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_newtype_variant<T>(self, name: &'static str, variant_index: u32, variant: &'static str, value: &T) -> Result<()>
|
fn serialize_newtype_variant<T>(self, _name: &'static str, _variant_index: u32, _variant: &'static str, _value: &T) -> Result<()>
|
||||||
where
|
where
|
||||||
T: ?Sized + Serialize
|
T: ?Sized + Serialize
|
||||||
{
|
{
|
||||||
@ -169,13 +209,18 @@ impl<'a> ser::Serializer for &'a mut Serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
|
fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.push('l' as u8);
|
self.output.push('l' as u8);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
|
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
|
||||||
println!("tuple");
|
if self.tuple_state != TupleState::None {
|
||||||
todo!()
|
return Err(Error::WontImplement)
|
||||||
|
}
|
||||||
|
self.tuple_state = TupleState::Unknown;
|
||||||
|
self.tuple_len = len;
|
||||||
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct> {
|
fn serialize_tuple_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeTupleStruct> {
|
||||||
@ -187,6 +232,7 @@ impl<'a> ser::Serializer for &'a mut Serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
|
fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.push('d' as u8);
|
self.output.push('d' as u8);
|
||||||
Ok(MapSerializer{
|
Ok(MapSerializer{
|
||||||
super_serializer: self,
|
super_serializer: self,
|
||||||
@ -197,6 +243,7 @@ impl<'a> ser::Serializer for &'a mut Serializer
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
|
fn serialize_struct(self, _name: &'static str, _len: usize) -> Result<Self::SerializeStruct> {
|
||||||
|
self.write_tuple_start_list();
|
||||||
self.output.push('d' as u8);
|
self.output.push('d' as u8);
|
||||||
Ok(MapSerializer{
|
Ok(MapSerializer{
|
||||||
super_serializer: self,
|
super_serializer: self,
|
||||||
@ -236,11 +283,15 @@ impl <'a> ser::SerializeTuple for &'a mut Serializer {
|
|||||||
where
|
where
|
||||||
T: ?Sized + Serialize
|
T: ?Sized + Serialize
|
||||||
{
|
{
|
||||||
todo!()
|
value.serialize(&mut **self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn end(self) -> Result<()> {
|
fn end(self) -> Result<()> {
|
||||||
todo!()
|
if self.tuple_state == TupleState::List {
|
||||||
|
self.output.push('e' as u8);
|
||||||
|
}
|
||||||
|
self.tuple_state = TupleState::None;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -385,7 +436,7 @@ impl <'a> ser::SerializeStructVariant for &'a mut Serializer {
|
|||||||
mod test {
|
mod test {
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use crate::bencode::ser::to_string;
|
use crate::bencode::ser::{to_bytes, to_string};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_int() {
|
fn test_int() {
|
||||||
@ -435,7 +486,7 @@ mod test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dict() {
|
fn test_struct() {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
struct A {
|
struct A {
|
||||||
a: i32,
|
a: i32,
|
||||||
@ -459,6 +510,26 @@ mod test {
|
|||||||
o2: None,
|
o2: None,
|
||||||
}).unwrap(),
|
}).unwrap(),
|
||||||
"d1:lli3ei7ei9ee1:md3:bari18e3:fooi23ee1:o3:baze"
|
"d1:lli3ei7ei9ee1:md3:bari18e3:fooi23ee1:o3:baze"
|
||||||
)
|
);
|
||||||
|
|
||||||
|
#[derive(Serialize)]
|
||||||
|
struct C {
|
||||||
|
d: HashMap<String, [u8; 3]>
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut expected = "d1:dd3:bar3:".as_bytes().to_vec();
|
||||||
|
expected.extend(vec![12, 18, 9]);
|
||||||
|
expected.extend("3:foo3:".as_bytes());
|
||||||
|
expected.extend(vec![1, 2, 3]);
|
||||||
|
expected.extend("ee".as_bytes());
|
||||||
|
|
||||||
|
assert_eq!(to_bytes(&C{
|
||||||
|
d: HashMap::from([
|
||||||
|
("foo".to_string(), [1, 2, 3]),
|
||||||
|
("bar".to_string(), [12, 18, 9]),
|
||||||
|
])
|
||||||
|
}).unwrap(),
|
||||||
|
expected
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user