Skip to content

Commit

Permalink
add serialization
Browse files Browse the repository at this point in the history
  • Loading branch information
apoelstra committed Apr 17, 2017
1 parent 7a32b77 commit 0c9c4e8
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ots"
version = "0.1.1"
version = "0.1.2"
authors = ["Andrew Poelstra <[email protected]>"]
license = "CC0-1.0"
homepage = "https://github.com/apoelstra/rust-ots/"
Expand Down
23 changes: 22 additions & 1 deletion src/attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
//!
use std::fmt;
use std::io::Read;
use std::io::{Read, Write};

use error::Error;
use hex::Hexed;
Expand Down Expand Up @@ -96,6 +96,27 @@ impl Attestation {
})
}
}

/// Serialize an attestation
pub fn serialize<W: Write>(&self, ser: &mut ser::Serializer<W>) -> Result<(), Error> {
let mut byte_ser = ser::Serializer::new(vec![]);
match *self {
Attestation::Bitcoin { height } => {
ser.write_fixed_bytes(BITCOIN_TAG)?;
byte_ser.write_uint(height)?;
ser.write_bytes(&byte_ser.into_inner())
}
Attestation::Pending { ref uri } => {
ser.write_fixed_bytes(PENDING_TAG)?;
byte_ser.write_bytes(uri.as_bytes())?;
ser.write_bytes(&byte_ser.into_inner())
}
Attestation::Unknown { ref tag, ref data } => {
ser.write_fixed_bytes(tag)?;
ser.write_bytes(data)
}
}
}
}

impl fmt::Display for Attestation {
Expand Down
14 changes: 13 additions & 1 deletion src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crypto::sha1::Sha1;
use crypto::sha2::Sha256;
use crypto::ripemd160::Ripemd160;
use std::fmt;
use std::io::Read;
use std::io::{Read, Write};

use error::Error;
use hex::Hexed;
Expand Down Expand Up @@ -87,6 +87,18 @@ impl Op {
}
}

/// Serialize the op into a serializer
pub fn serialize<W: Write>(&self, ser: &mut ser::Serializer<W>) -> Result<(), Error> {
ser.write_byte(self.tag())?;
if let Op::Append(ref data) = *self {
ser.write_bytes(data)?;
}
if let Op::Prepend(ref data) = *self {
ser.write_bytes(data)?;
}
Ok(())
}

/// Execute an op on the given data
pub fn execute(&self, input: &[u8]) -> Vec<u8> {
match *self {
Expand Down
24 changes: 14 additions & 10 deletions src/ser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,19 @@ impl DetachedTimestampFile {
timestamp: timestamp
})
}

/// Serialize the file into a reader
pub fn to_writer<W: Write>(&self, writer: W) -> Result<(), Error> {
let mut ser = Serializer::new(writer);
ser.write_magic()?;
ser.write_version()?;
ser.write_byte(self.digest_type.to_tag())?;
// We write timestamp.start_digest here and not in `Timestamp::serialize`
// to copy the way that python-opentimestamps is structured, though it is
// an abstraction violation
ser.write_fixed_bytes(&self.timestamp.start_digest)?;
self.timestamp.serialize(&mut ser)
}
}

impl fmt::Display for DetachedTimestampFile {
Expand Down Expand Up @@ -247,19 +260,10 @@ impl<W: Write> Serializer<W> {
}

/// Writes a single byte to the writer
fn write_byte(&mut self, byte: u8) -> Result<(), Error> {
pub fn write_byte(&mut self, byte: u8) -> Result<(), Error> {
self.writer.write_all(&[byte]).map_err(Error::Io)
}

/// Write a boolean
pub fn write_bool(&mut self, b: bool) -> Result<(), Error> {
if b {
self.write_byte(0xff)
} else {
self.write_byte(0x00)
}
}

/// Write an unsigned integer
pub fn write_uint(&mut self, mut n: usize) -> Result<(), Error> {
if n == 0 {
Expand Down
28 changes: 26 additions & 2 deletions src/timestamp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
//!
use std::fmt;
use std::io::Read;
use std::io::{Read, Write};

use attestation::Attestation;
use error::Error;
Expand Down Expand Up @@ -61,7 +61,6 @@ pub struct Timestamp {
impl Timestamp {
/// Deserialize one step in a timestamp.
fn deserialize_step_recurse<R: Read>(deser: &mut ser::Deserializer<R>, input_digest: Vec<u8>, tag: Option<u8>, recursion_limit: usize) -> Result<Step, Error> {

if recursion_limit == 0 {
return Err(Error::StackOverflow);
}
Expand Down Expand Up @@ -128,6 +127,31 @@ impl Timestamp {
first_step: first_step
})
}

fn serialize_step_recurse<W: Write>(ser: &mut ser::Serializer<W>, step: &Step) -> Result<(), Error> {
match step.data {
StepData::Fork => {
for i in 0..step.next.len() - 1 {
ser.write_byte(0xff)?;
Timestamp::serialize_step_recurse(ser, &step.next[i])?;
}
Timestamp::serialize_step_recurse(ser, &step.next[step.next.len() - 1])
}
StepData::Op(ref op) => {
op.serialize(ser)?;
Timestamp::serialize_step_recurse(ser, &step.next[0])
}
StepData::Attestation(ref attest) => {
ser.write_byte(0x00)?;
attest.serialize(ser)
}
}
}

/// Serialize a timestamp
pub fn serialize<W: Write>(&self, ser: &mut ser::Serializer<W>) -> Result<(), Error> {
Timestamp::serialize_step_recurse(ser, &self.first_step)
}
}

fn fmt_recurse(step: &Step, f: &mut fmt::Formatter, depth: usize, first_line: bool) -> fmt::Result {
Expand Down

0 comments on commit 0c9c4e8

Please sign in to comment.