Skip to content
This repository has been archived by the owner on Aug 15, 2024. It is now read-only.

Commit

Permalink
add serde serialization/deserialization as de-facto rust standard
Browse files Browse the repository at this point in the history
  • Loading branch information
shamatar committed Jan 9, 2019
1 parent 661558e commit 056a13b
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 12 deletions.
14 changes: 9 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
[package]
name = "ff"
version = "0.4.0"
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
version = "0.5.0"
authors = ["Sean Bowe <ewillbefull@gmail.com>",
"Alex Gluchowski <alex@gluchowski.net>",
"Alex Vlasov <alex.m.vlasov@gmail.com>"]
description = "Library for building and interfacing with finite fields"
documentation = "https://docs.rs/ff/"
homepage = "https://github.com/ebfull/ff"
homepage = "https://github.com/matterinc/ff"
license = "MIT/Apache-2.0"
repository = "https://github.com/ebfull/ff"
repository = "https://github.com/matterinc/ff"

[dependencies]
byteorder = "1"
rand = "0.4"
ff_derive = { version = "0.3.0", path = "ff_derive", optional = true }
ff_derive = { version = "0.4.0", path = "ff_derive", optional = true }
#ff_asm = { version = "0.0.1", path = "ff_asm", optional = true }

[features]
default = []
derive = ["ff_derive"]
#asm = ["ff_asm"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ First, enable the `derive` crate feature:

```toml
[dependencies]
ff = { version = "0.4", features = ["derive"] }
ff = { path = "../ff", features = ["derive"] }
```

And then use the macro like so:
Expand Down
11 changes: 7 additions & 4 deletions ff_derive/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
[package]
name = "ff_derive"
version = "0.3.0"
authors = ["Sean Bowe <ewillbefull@gmail.com>"]
version = "0.4.0"
authors = ["Sean Bowe <ewillbefull@gmail.com>",
"Alex Gluchowski <alex@gluchowski.net>",
"Alex Vlasov <alex.m.vlasov@gmail.com>"]
description = "Procedural macro library used to build custom prime field implementations"
documentation = "https://docs.rs/ff/"
homepage = "https://github.com/ebfull/ff"
homepage = "https://github.com/matterinc/ff"
license = "MIT/Apache-2.0"
repository = "https://github.com/ebfull/ff"
repository = "https://github.com/matterinc/ff"

[lib]
proc-macro = true
Expand All @@ -18,3 +20,4 @@ num-integer = "0.1"
proc-macro2 = "0.4"
quote = "0.6"
syn = "0.14"
serde_derive = "1.0.80"
73 changes: 71 additions & 2 deletions ff_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ extern crate syn;
#[macro_use]
extern crate quote;

extern crate serde_derive;

extern crate num_bigint;
extern crate num_integer;
extern crate num_traits;
Expand Down Expand Up @@ -121,8 +123,12 @@ fn fetch_attr(name: &str, attrs: &[syn::Attribute]) -> Option<String> {
// Implement PrimeFieldRepr for the wrapped ident `repr` with `limbs` limbs.
fn prime_field_repr_impl(repr: &syn::Ident, limbs: usize) -> proc_macro2::TokenStream {
quote! {
#[derive(Copy, Clone, PartialEq, Eq, Default)]
pub struct #repr(pub [u64; #limbs]);

#[derive(Copy, Clone, PartialEq, Eq, Default, Serialize, Deserialize)]
pub struct #repr(
//#[serde(with = "SerHex::<StrictPfx>")]
pub [u64; #limbs]
);

impl ::std::fmt::Debug for #repr
{
Expand Down Expand Up @@ -901,6 +907,7 @@ fn prime_field_impl(
fn root_of_unity() -> Self {
#name(ROOT_OF_UNITY)
}

}

impl ::ff::Field for #name {
Expand Down Expand Up @@ -1029,6 +1036,12 @@ fn prime_field_impl(
}
}

impl std::default::Default for #name {
fn default() -> Self {
Self::zero()
}
}

impl #name {
/// Determines if the element is really in the field. This is only used
/// internally.
Expand Down Expand Up @@ -1060,6 +1073,62 @@ fn prime_field_impl(

self.reduce();
}

pub fn to_hex(&self) -> String {
let mut buf: Vec<u8> = vec![];
self.into_repr().write_be(&mut buf).unwrap();
hex::encode(&buf)
}

pub fn from_hex(value: &str) -> Result<#name, String> {
let value = if value.starts_with("0x") { &value[2..] } else { value };
if value.len() % 2 != 0 {return Err(format!("hex length must be even for full byte encoding: {}", value))}
let mut buf = hex::decode(&value).map_err(|_| format!("could not decode hex: {}", value))?;
buf.reverse();
buf.resize(#limbs * 8, 0);
let mut repr = #repr::default();
repr.read_le(&buf[..]).map_err(|e| format!("could not read {}: {}", value, &e))?;
#name::from_repr(repr).map_err(|e| format!("could not convert into prime field: {}: {}", value, &e))
}
}

impl serde::Serialize for #name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&format!("0x{}", &self.to_hex()))
}
}

use std::fmt;

use serde::de::{self, Visitor};

struct FrVisitor;

impl<'de> Visitor<'de> for FrVisitor {
type Value = #name;

fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a hex string with prefix: 0x012ab...")
}

fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
#name::from_hex(&value[2..]).map_err(|e| E::custom(e))
}
}

impl<'de> serde::Deserialize<'de> for #name {
fn deserialize<D>(deserializer: D) -> Result<#name, D::Error>
where
D: serde::Deserializer<'de>,
{
deserializer.deserialize_str(FrVisitor)
}
}
}
}
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ extern crate ff_derive;
#[cfg(feature = "derive")]
pub use ff_derive::*;

// #[cfg(feature = "asm")]
// pub use ff_asm::*;

use std::error::Error;
use std::fmt;
use std::io::{self, Read, Write};
Expand Down

0 comments on commit 056a13b

Please sign in to comment.