1use super::{schema::Schema, traits::ToSchema};
2use anchor_lang::prelude::*;
3use std::{io::Read, str::FromStr};
4
5#[cfg(feature = "compression")]
6use crate::compression::ToNode;
7use crate::{errors::HplToolkitError, utils::VecMap};
8#[cfg(feature = "compression")]
9use anchor_lang::solana_program::keccak;
10
11#[cfg_attr(feature = "debug", derive(Debug))]
12#[cfg_attr(feature = "compression", derive(ToNode))]
13#[derive(AnchorDeserialize, AnchorSerialize, Clone, PartialEq)]
14pub enum Number {
15 U64(u64),
16 I64(i64),
17 F64(f64),
18}
19
20impl ToString for Number {
21 fn to_string(&self) -> String {
22 match self {
23 Self::U64(data) => data.to_string(),
24 Self::I64(data) => data.to_string(),
25 Self::F64(data) => data.to_string(),
26 }
27 }
28}
29
30impl Into<serde_json::Number> for Number {
31 fn into(self) -> serde_json::Number {
32 match self {
33 Self::U64(value) => serde_json::Number::from(value),
34 Self::I64(value) => serde_json::Number::from(value),
35 Self::F64(value) => serde_json::Number::from_f64(value).unwrap(),
36 }
37 }
38}
39
40impl From<serde_json::Number> for Number {
41 fn from(number: serde_json::Number) -> Self {
42 if let Some(number) = number.as_u64() {
43 Self::U64(number)
44 } else if let Some(number) = number.as_i64() {
45 Self::I64(number)
46 } else if let Some(number) = number.as_f64() {
47 Self::F64(number)
48 } else {
49 panic!("Serde Number cannot be converted to Number")
50 }
51 }
52}
53
54#[cfg_attr(feature = "debug", derive(Debug))]
55#[cfg_attr(feature = "compression", derive(ToNode))]
56#[cfg_attr(feature = "idl-build", derive(hpl_toolkit_derive_gen_idl::GenIdl))]
57#[derive(Clone, PartialEq)]
58pub enum SchemaValue {
59 Null,
60 Bool(bool),
61 Number(Number),
62 String(String),
63 Array(Vec<Self>),
64 Object(VecMap<String, Self>),
65 Pubkey(Pubkey),
66 VecMap(VecMap<Self, Self>),
67 Enum(String, Box<Self>),
68 Schema(Schema),
69}
70impl ToSchema for SchemaValue {
77 fn schema() -> Schema {
78 Schema::Null
80 }
81
82 fn schema_value(&self) -> Self {
83 self.clone()
84 }
85}
86
87impl SchemaValue {
88 pub fn validate(&mut self, schema: &Schema) -> bool {
89 match schema {
90 Schema::Null => matches!(self, Self::Null),
91 Schema::Bool => matches!(self, Self::Bool(_)),
92 Schema::Number => matches!(self, Self::Number(_)),
93 Schema::String => matches!(self, Self::String(_)),
94 Schema::Array(schema) => match self {
95 Self::Array(arr) => arr.iter_mut().all(|value| value.validate(schema)),
96 _ => false,
97 },
98 Schema::Object(schema) => match self {
99 Self::Object(obj) => schema.iter().all(|(key, schema)| {
100 if let Some(value) = obj.get_mut(key) {
101 return value.validate(schema);
102 } else if matches!(schema, Schema::Option(_)) {
103 return true;
104 } else if matches!(schema, Schema::Null) {
105 obj.insert(key.to_owned(), Self::Null);
106 return true;
107 }
108 false
109 }),
110 _ => false,
111 },
112 Schema::Pubkey => matches!(self, Self::Pubkey(_)),
113 Schema::Option(schema) => self.validate(&Schema::Null) || self.validate(schema),
114 Schema::VecMap(_k, v) => match self {
115 Self::VecMap(map) => map.iter_mut().all(|(_, value)| value.validate(v)),
116 _ => false,
117 },
118 Schema::Enum(variants) => match self {
119 Self::Enum(variant_kind, variant_value) => variants
120 .iter()
121 .find(|variant| {
122 return variant.0.eq(variant_kind) && variant_value.validate(&variant.1);
123 })
124 .is_some(),
125 _ => false,
126 },
127 Schema::Any => true,
128 }
129 }
130
131 pub fn size(&self) -> usize {
132 match self {
133 Self::Null => 1,
134 Self::Bool(_) => 2,
135 Self::Number(_) => 1 + 8,
136 Self::String(string) => 1 + string.as_bytes().len(),
137 Self::Array(vec) => {
138 let mut size = 1;
139 for schema in vec {
140 size += schema.size()
141 }
142 size
143 }
144 Self::Object(map) => {
145 let mut size = 1;
146 for (key, value) in map.iter() {
147 size += key.as_bytes().len();
148 size += value.size();
149 }
150 size
151 }
152 Self::Pubkey(_) => 1 + 32,
153 Self::VecMap(map) => {
154 let mut size = 1;
155 for (key, value) in map.iter() {
156 size += key.size();
157 size += value.size();
158 }
159 size
160 }
161 Self::Enum(kind, value) => 1 + kind.as_bytes().len() + value.size(),
162 Self::Schema(schema) => 1 + schema.size(),
163 }
164 }
165
166 pub fn size_for_borsh(&self) -> usize {
167 match self.try_to_vec() {
168 Ok(vec) => vec.len(),
169 Err(_) => 0,
170 }
171 }
172}
173
174impl ToString for SchemaValue {
175 fn to_string(&self) -> String {
176 let mut schema_value_str = String::new();
177 match self {
178 Self::Null => schema_value_str.push_str("null"),
179 Self::Bool(data) => schema_value_str.push_str(data.to_string().as_str()),
180 Self::Number(data) => schema_value_str.push_str(data.to_string().as_str()),
181 Self::String(data) => schema_value_str.push_str(format!("\"{}\"", data).as_str()),
182 Self::Array(data) => {
183 schema_value_str.push_str("[ ");
184 data.iter().for_each(|value| {
185 schema_value_str.push_str(format!("{}, ", value.to_string()).as_str());
186 });
187 schema_value_str.push_str("]");
188 }
189 Self::Object(data) => {
190 schema_value_str.push_str("{ ");
191 data.iter().for_each(|(key, value)| {
192 schema_value_str.push_str(format!("{}: {}, ", key, value.to_string()).as_str());
193 });
194 schema_value_str.push_str("}");
195 }
196 Self::Pubkey(data) => schema_value_str.push_str(data.to_string().as_str()),
197 Self::VecMap(data) => {
198 schema_value_str.push_str("Map { ");
199 data.iter().for_each(|(key, value)| {
200 schema_value_str
201 .push_str(format!("{}: {}, ", key.to_string(), value.to_string()).as_str());
202 });
203 schema_value_str.push_str("}");
204 }
205 Self::Enum(kind, value) => {
206 schema_value_str.push_str(&format!("Enum {{ {}: {} }}", kind, value.to_string()))
207 }
208 Self::Schema(schema) => {
209 schema_value_str.push_str(&format!("Schema {}", schema.to_string()))
210 }
211 };
212 schema_value_str
213 }
214}
215
216impl AnchorSerialize for SchemaValue {
217 #[inline]
218 fn serialize<W: std::io::prelude::Write>(&self, writer: &mut W) -> std::io::Result<()> {
219 match self {
220 Self::Null => 0u8.serialize(writer),
221 Self::Bool(value) => {
222 1u8.serialize(writer)?;
223 value.serialize(writer)
224 }
225 Self::Number(value) => {
226 2u8.serialize(writer)?;
227 value.serialize(writer)
228 }
229 Self::String(value) => {
230 3u8.serialize(writer)?;
231 value.serialize(writer)
232 }
233 Self::Array(value) => {
234 4u8.serialize(writer)?;
235 value.serialize(writer)
236 }
237 Self::Object(value) => {
238 5u8.serialize(writer)?;
239 value.serialize(writer)
240 }
241 Self::Pubkey(value) => {
242 6u8.serialize(writer)?;
243 value.serialize(writer)
244 }
245 Self::VecMap(value) => {
246 7u8.serialize(writer)?;
247 value.serialize(writer)
248 }
249 Self::Enum(kind, value) => {
250 8u8.serialize(writer)?;
251 kind.serialize(writer)?;
252 value.serialize(writer)
253 }
254 Self::Schema(schema) => {
255 9u8.serialize(writer)?;
256 schema.serialize(writer)
257 }
258 }
259 }
260}
261
262impl AnchorDeserialize for SchemaValue {
263 #[inline]
264 fn deserialize_reader<R: std::io::prelude::Read>(reader: &mut R) -> std::io::Result<Self> {
265 #[cfg(feature = "log")]
266 crate::logger::debug!("Processing SchemaValue");
267 let mut buf: [u8; 1] = [0; 1];
268 let limit = reader.read(&mut buf)?;
269 if limit != 1 {
270 #[cfg(feature = "log")]
271 crate::logger::debug!("limit: {}, Buf: {:?}", limit, buf);
272 return Err(std::io::Error::new(
273 std::io::ErrorKind::InvalidInput,
274 "Unexpected length of input",
275 ));
276 }
277
278 #[cfg(feature = "log")]
279 crate::logger::debug!("SchemaValue Processing buf: {:?}", buf);
280 let result = match buf[0] {
281 0 => Ok(Self::Null),
282 1 => bool::deserialize_reader(reader).and_then(|v| Ok(Self::Bool(v))),
283 2 => Number::deserialize_reader(reader).and_then(|v| Ok(Self::Number(v))),
284 3 => String::deserialize_reader(reader).and_then(|v| Ok(Self::String(v))),
285 4 => Vec::deserialize_reader(reader).and_then(|v| Ok(Self::Array(v))),
286 5 => VecMap::deserialize_reader(reader).and_then(|v| Ok(Self::Object(v))),
287 6 => Pubkey::deserialize_reader(reader).and_then(|v| Ok(Self::Pubkey(v))),
288 7 => VecMap::deserialize_reader(reader).and_then(|v| Ok(Self::VecMap(v))),
289 8 => Ok(Self::Enum(
290 String::deserialize_reader(reader)?,
291 Box::new(Self::deserialize_reader(reader)?),
292 )),
293 9 => Schema::deserialize_reader(reader).and_then(|v| Ok(Self::Schema(v))),
294 _ => {
295 let msg = format!(
296 "Invalid Option representation: {}. The first byte must be 0 till 6",
297 buf[0]
298 );
299 Err(std::io::Error::new(std::io::ErrorKind::InvalidInput, msg))
300 }
301 };
302
303 if result.is_err() {
304 let mut vec = Vec::<u8>::new();
305 reader.read_to_end(&mut vec)?;
306 #[cfg(feature = "log")]
307 crate::logger::error!(
308 "SchemaValue Failed at buf: {:?}, Bytes remaining: {:?}",
309 buf,
310 vec
311 );
312 }
313
314 result
315 }
316}
317const PUBKEY_PREFIX: &'static str = "pubkey:";
318const VEC_MAP_PREFIX: &'static str = "_is_a_vec_map_hc";
319impl Into<serde_json::Value> for SchemaValue {
320 fn into(self) -> serde_json::Value {
321 match self {
322 Self::Null => serde_json::Value::Null,
323 Self::Bool(value) => serde_json::Value::Bool(value),
324 Self::Number(value) => serde_json::Value::Number(value.into()),
325 Self::String(value) => serde_json::Value::String(value),
326 Self::Array(value) => {
327 serde_json::Value::Array(value.into_iter().map(|i| i.into()).collect())
328 }
329 Self::Object(value) => {
330 serde_json::Value::Object(value.into_iter().map(|(k, v)| (k, v.into())).collect())
331 }
332 Self::Pubkey(value) => {
333 let string = format!("{}{}", PUBKEY_PREFIX, value.to_string());
334 serde_json::Value::String(string)
335 }
336 Self::VecMap(value) => {
337 let mut vec = value
338 .into_iter()
339 .map(|(k, v)| serde_json::Value::Array(vec![k.into(), v.into()]))
340 .collect::<Vec<_>>();
341
342 vec.insert(0, serde_json::Value::String(VEC_MAP_PREFIX.to_string()));
344
345 serde_json::Value::Array(vec)
346 }
347 Self::Enum(kind, value) => {
348 let mut obj = serde_json::Map::<String, serde_json::Value>::new();
349 obj.insert(String::from("__kind"), kind.into());
350
351 let schema_value = value.as_ref().to_owned();
352 obj.insert(String::from("params"), schema_value.into());
353
354 serde_json::Value::Object(obj)
355 }
356 Self::Schema(schema) => schema.pack(),
357 }
358 }
359}
360
361impl From<serde_json::Value> for SchemaValue {
362 fn from(value: serde_json::Value) -> Self {
363 if let Some(schema) = Schema::try_unpack(&value) {
364 return Self::Schema(schema);
365 }
366 match value {
367 serde_json::Value::Null => Self::Null,
368 serde_json::Value::Bool(value) => Self::Bool(value),
369 serde_json::Value::Number(value) => Self::Number(value.into()),
370 serde_json::Value::String(value) => {
371 if value.starts_with(PUBKEY_PREFIX) && value.len() == (PUBKEY_PREFIX.len() + 32) {
372 let pubkey = Pubkey::from_str(value.split_at(PUBKEY_PREFIX.len()).1).unwrap();
373 return Self::Pubkey(pubkey);
374 }
375 Self::String(value)
376 }
377 serde_json::Value::Array(value) => {
378 if let Some(serde_json::Value::String(prefix)) = value.get(0) {
379 if *prefix == VEC_MAP_PREFIX.to_string() {
380 let mut map = VecMap::new();
381 for i in 1..value.len() {
382 if let serde_json::Value::Array(vec) = &value[i] {
383 if vec.len() == 2 {
384 map.insert(vec[0].to_owned().into(), vec[1].to_owned().into());
385 }
386 }
387 }
388 return Self::VecMap(map);
389 }
390 }
391 Self::Array(value.into_iter().map(|i| i.into()).collect())
392 }
393 serde_json::Value::Object(value) => {
394 if let Some(kind) = value.get("__kind") {
395 if let serde_json::Value::String(kind) = kind {
396 let params = if let Some(params) = value.get("params") {
397 params.to_owned().into()
398 } else {
399 Self::Null
400 };
401
402 return Self::Enum(kind.to_owned(), Box::new(params));
403 }
404 }
405 Self::Object(value.into_iter().map(|(k, v)| (k, v.into())).collect())
406 }
407 }
408 }
409}
410
411#[cfg_attr(feature = "debug", derive(Debug))]
412#[cfg_attr(feature = "compression", derive(ToNode))]
413#[derive(Clone, PartialEq)]
414pub struct SchemaValueContainer {
415 parsed: Option<SchemaValue>,
416 raw: Option<Vec<u8>>,
417}
418
419#[cfg(feature = "idl-build")]
420use anchor_lang::idl::types::*;
421#[cfg(feature = "idl-build")]
422impl anchor_lang::idl::build::IdlBuild for SchemaValueContainer {
423 fn get_full_path() -> String {
424 format!(
425 "{0}::{1}",
426 "hpl_toolkit::schema_value", "SchemaValueContainer",
427 )
428 }
429
430 fn create_type() -> Option<IdlTypeDef> {
431 Some(IdlTypeDef {
432 name: "SchemaValueContainer".to_string(),
433 docs: vec![],
434 serialization: IdlSerialization::Borsh,
435 repr: None,
436 generics: vec![],
437 ty: IdlTypeDefTy::Struct {
438 fields: Some(IdlDefinedFields::Named(vec![IdlField {
439 name: "raw".to_string(),
440 ty: IdlType::Vec(Box::new(IdlType::U8)),
441 docs: vec![],
442 }])),
443 },
444 })
445 }
446
447 fn insert_types(_types: &mut std::collections::BTreeMap<String, IdlTypeDef>) {
448 _types.insert(
449 "SchemaValue".to_string(),
450 SchemaValue::create_type().unwrap(),
451 );
452 _types.insert("Number".to_string(), super::Number::create_type().unwrap());
453 }
454}
455impl ToSchema for SchemaValueContainer {
456 fn schema() -> Schema {
457 SchemaValue::schema()
458 }
459 fn schema_value(&self) -> SchemaValue {
460 if let Some(schema) = &self.parsed {
461 return schema.clone();
462 } else if let Some(bytes) = &self.raw {
463 if let Ok(schema) = SchemaValue::deserialize(&mut &bytes[..]) {
464 return schema;
465 }
466 }
467 SchemaValue::Null
468 }
469}
470impl AnchorDeserialize for SchemaValueContainer {
471 fn deserialize_reader<R: std::io::prelude::Read>(reader: &mut R) -> std::io::Result<Self> {
472 let buffer = Vec::<u8>::deserialize_reader(reader)?;
473 Ok(Self {
474 parsed: None,
475 raw: Some(buffer),
476 })
477 }
478}
479impl AnchorSerialize for SchemaValueContainer {
480 fn serialize<W: std::io::Write>(&self, writer: &mut W) -> std::io::Result<()> {
481 if let Some(bytes) = &self.raw {
482 bytes.serialize(writer)?;
483 } else if let Some(schema) = &self.parsed {
484 let bytes = schema.try_to_vec()?;
485 bytes.serialize(writer)?;
486 } else {
487 return Err(std::io::Error::from(std::io::ErrorKind::InvalidData));
488 };
489 Ok(())
490 }
491}
492
493impl SchemaValueContainer {
494 pub fn size(&self) -> usize {
495 if let Some(bytes) = &self.raw {
496 return bytes.len() + 4;
497 } else if let Some(schema) = &self.parsed {
498 return schema.size() + 4;
499 }
500
501 0
502 }
503 pub fn new(schema: SchemaValue) -> Self {
504 Self {
505 raw: None,
506 parsed: Some(schema),
507 }
508 }
509
510 pub fn new_from_bytes(bytes: Vec<u8>) -> Self {
511 Self {
512 raw: Some(bytes),
513 parsed: None,
514 }
515 }
516
517 pub fn parse(&mut self) -> Result<()> {
518 if self.parsed.is_none() {
519 if self.raw.is_none() {
520 return Err(HplToolkitError::SchemaValueContainerEmpty.into());
521 }
522 self.parsed = Some(SchemaValue::deserialize(
523 &mut &self.raw.take().unwrap()[..],
524 )?)
525 }
526 Ok(())
527 }
528 pub fn get_inner(&mut self) -> Result<&SchemaValue> {
529 self.parse()?;
530 Ok(self.parsed.as_ref().unwrap())
531 }
532
533 pub fn get_inner_mut(&mut self) -> Result<&mut SchemaValue> {
534 self.parse()?;
535 Ok(self.parsed.as_mut().unwrap())
536 }
537}