Skip to content

Commit

Permalink
feat: add to_xdr and from_xdr
Browse files Browse the repository at this point in the history
  • Loading branch information
willemneal committed Mar 18, 2024
1 parent 17efe8f commit c52da3d
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/target

.DS_Store
1 change: 1 addition & 0 deletions crates/stellar-xdr-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ crate-type = ["cdylib", "rlib"]

[features]
default = ["console_error_panic_hook"]
schema = []

[dependencies]
wasm-bindgen = "0.2.84"
Expand Down
91 changes: 83 additions & 8 deletions crates/stellar-xdr-wasm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
mod utils;

use stellar_xdr::{curr::TypeVariant, schema::Schema};
use std::{
cmp,
convert::TryInto,
io::{self, Read},
str::FromStr,
};

use stellar_xdr::{
curr::{self, TypeVariant, WriteXdr},
schema::Schema,
};
use wasm_bindgen::prelude::*;

#[wasm_bindgen]
Expand All @@ -15,12 +25,77 @@ pub fn type_variants() -> String {
)
}

// #[cfg(feature = "schema")]
#[wasm_bindgen]
pub fn schema(s: &str) -> String {
let Schema(json_schema): Schema = s.parse().unwrap();
let s = match serde_json::to_string(&json_schema) {
Ok(s) => s,
Err(e) => return format!("{{\"error\": \"{}\"}}", e),
};
s
pub fn schema(type_variant: &str) -> String {
let Schema(json_schema): Schema = type_variant.parse().unwrap();
serde_json::to_string(&json_schema).unwrap_or_else(|e| format!("{{\"error\": \"{e}\"}}"))
}

#[wasm_bindgen]
pub fn transaction() -> String {
let Schema(json_schema): Schema = TypeVariant::Transaction.try_into().unwrap();
serde_json::to_string(&json_schema).unwrap_or_else(|e| format!("{{\"error\": \"{e}\"}}"))
}

#[wasm_bindgen]
pub fn from_xdr(xdr_base64: String, variant: Option<String>) -> String {
let mut f = curr::Limited::new(ResetRead::new(xdr_base64.as_bytes()), curr::Limits::none());
for variant in variant
.map(|v| Some(vec![v.parse::<crate::curr::TypeVariant>().ok()?]))
.unwrap_or_else(|| Some(TypeVariant::VARIANTS.to_vec()))
.unwrap()
{
f.inner.reset();
if let Ok(res) = curr::Type::read_xdr_to_end(variant, &mut f) {
return serde_json::to_string(&res)
.unwrap_or_else(|e| format!("{{\"error\": \"{e}\"}}"));
}
}
"{\"error\": \"unknown type\"}".to_string()
}

#[wasm_bindgen]
pub fn to_xdr(json_string: String, variant: String) -> String {
let r#type = TypeVariant::from_str(&variant).unwrap();
let t = curr::Type::read_json(r#type, json_string.as_bytes()).unwrap();
t.to_xdr_base64(curr::Limits::none()).unwrap()
}

struct ResetRead<R: Read> {
read: R,
buf: Vec<u8>,
cursor: usize,
}

impl<R: Read> ResetRead<R> {
fn new(r: R) -> Self {
Self {
read: r,
buf: Vec::new(),
cursor: 0,
}
}

fn reset(&mut self) {
self.cursor = 0;
}
}

impl<R: Read> Read for ResetRead<R> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
// Read from the buffer first into buf.
let n = cmp::min(self.buf.len() - self.cursor, buf.len());
buf[..n].copy_from_slice(&self.buf[self.cursor..self.cursor + n]);
// Read from the reader and cache the result in the buf if the buf is consumed.
if n < buf.len() {
let read_n = self.read.read(buf)?;
self.buf.extend_from_slice(&buf[n..n + read_n]);
self.cursor += n + read_n;
Ok(n + read_n)
} else {
self.cursor += n;
Ok(n)
}
}
}

0 comments on commit c52da3d

Please sign in to comment.