Struct cardano_serialization_lib::plutus::PlutusMap
source · pub struct PlutusMap(_);
Implementations§
source§impl PlutusMap
impl PlutusMap
pub fn from_bytes(bytes: Vec<u8>) -> Result<PlutusMap, DeserializeError>
source§impl PlutusMap
impl PlutusMap
sourcepub fn new() -> Self
pub fn new() -> Self
Examples found in repository?
src/plutus.rs (line 1106)
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
pub fn encode_json_value_to_plutus_datum(
value: serde_json::Value,
schema: PlutusDatumSchema,
) -> Result<PlutusData, JsError> {
use serde_json::Value;
fn encode_number(x: serde_json::Number) -> Result<PlutusData, JsError> {
if let Some(x) = x.as_u64() {
Ok(PlutusData::new_integer(&BigInt::from(x)))
} else if let Some(x) = x.as_i64() {
Ok(PlutusData::new_integer(&BigInt::from(x)))
} else {
Err(JsError::from_str("floats not allowed in plutus datums"))
}
}
fn encode_string(
s: &str,
schema: PlutusDatumSchema,
is_key: bool,
) -> Result<PlutusData, JsError> {
if schema == PlutusDatumSchema::BasicConversions {
if s.starts_with("0x") {
// this must be a valid hex bytestring after
hex::decode(&s[2..])
.map(|bytes| PlutusData::new_bytes(bytes))
.map_err(|err| JsError::from_str(&format!("Error decoding {}: {}", s, err)))
} else if is_key {
// try as an integer
BigInt::from_str(s)
.map(|x| PlutusData::new_integer(&x))
// if not, we use the utf8 bytes of the string instead directly
.or_else(|_err| Ok(PlutusData::new_bytes(s.as_bytes().to_vec())))
} else {
// can only be UTF bytes if not in a key and not prefixed by 0x
Ok(PlutusData::new_bytes(s.as_bytes().to_vec()))
}
} else {
if s.starts_with("0x") {
Err(JsError::from_str("Hex byte strings in detailed schema should NOT start with 0x and should just contain the hex characters"))
} else {
hex::decode(s)
.map(|bytes| PlutusData::new_bytes(bytes))
.map_err(|e| JsError::from_str(&e.to_string()))
}
}
}
fn encode_array(
json_arr: Vec<Value>,
schema: PlutusDatumSchema,
) -> Result<PlutusData, JsError> {
let mut arr = PlutusList::new();
for value in json_arr {
arr.add(&encode_json_value_to_plutus_datum(value, schema)?);
}
Ok(PlutusData::new_list(&arr))
}
match schema {
PlutusDatumSchema::BasicConversions => match value {
Value::Null => Err(JsError::from_str("null not allowed in plutus datums")),
Value::Bool(_) => Err(JsError::from_str("bools not allowed in plutus datums")),
Value::Number(x) => encode_number(x),
// no strings in plutus so it's all bytes (as hex or utf8 printable)
Value::String(s) => encode_string(&s, schema, false),
Value::Array(json_arr) => encode_array(json_arr, schema),
Value::Object(json_obj) => {
let mut map = PlutusMap::new();
for (raw_key, raw_value) in json_obj {
let key = encode_string(&raw_key, schema, true)?;
let value = encode_json_value_to_plutus_datum(raw_value, schema)?;
map.insert(&key, &value);
}
Ok(PlutusData::new_map(&map))
}
},
PlutusDatumSchema::DetailedSchema => match value {
Value::Object(obj) => {
if obj.len() == 1 {
// all variants except tagged constructors
let (k, v) = obj.into_iter().next().unwrap();
fn tag_mismatch() -> JsError {
JsError::from_str("key does not match type")
}
match k.as_str() {
"int" => match v {
Value::Number(x) => encode_number(x),
_ => Err(tag_mismatch()),
},
"bytes" => {
encode_string(v.as_str().ok_or_else(tag_mismatch)?, schema, false)
}
"list" => {
encode_array(v.as_array().ok_or_else(tag_mismatch)?.clone(), schema)
}
"map" => {
let mut map = PlutusMap::new();
fn map_entry_err() -> JsError {
JsError::from_str("entry format in detailed schema map object not correct. Needs to be of form {\"k\": {\"key_type\": key}, \"v\": {\"value_type\", value}}")
}
for entry in v.as_array().ok_or_else(tag_mismatch)? {
let entry_obj = entry.as_object().ok_or_else(map_entry_err)?;
let raw_key = entry_obj.get("k").ok_or_else(map_entry_err)?;
let value = entry_obj.get("v").ok_or_else(map_entry_err)?;
let key =
encode_json_value_to_plutus_datum(raw_key.clone(), schema)?;
map.insert(
&key,
&encode_json_value_to_plutus_datum(value.clone(), schema)?,
);
}
Ok(PlutusData::new_map(&map))
}
invalid_key => Err(JsError::from_str(&format!(
"key '{}' in tagged object not valid",
invalid_key
))),
}
} else {
// constructor with tagged variant
if obj.len() != 2 {
return Err(JsError::from_str("detailed schemas must either have only one of the following keys: \"int\", \"bytes\", \"list\" or \"map\", or both of these 2 keys: \"constructor\" + \"fields\""));
}
let variant: BigNum = obj
.get("constructor")
.and_then(|v| Some(to_bignum(v.as_u64()?)))
.ok_or_else(|| JsError::from_str("tagged constructors must contain an unsigned integer called \"constructor\""))?;
let fields_json =
obj.get("fields")
.and_then(|f| f.as_array())
.ok_or_else(|| {
JsError::from_str(
"tagged constructors must contian a list called \"fields\"",
)
})?;
let mut fields = PlutusList::new();
for field_json in fields_json {
let field = encode_json_value_to_plutus_datum(field_json.clone(), schema)?;
fields.add(&field);
}
Ok(PlutusData::new_constr_plutus_data(&ConstrPlutusData::new(
&variant, &fields,
)))
}
}
_ => Err(JsError::from_str(&format!(
"DetailedSchema requires ALL JSON to be tagged objects, found: {}",
value
))),
},
}
}
pub fn len(&self) -> usize
sourcepub fn insert(
&mut self,
key: &PlutusData,
value: &PlutusData
) -> Option<PlutusData>
pub fn insert(
&mut self,
key: &PlutusData,
value: &PlutusData
) -> Option<PlutusData>
Examples found in repository?
src/plutus.rs (line 1110)
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190
pub fn encode_json_value_to_plutus_datum(
value: serde_json::Value,
schema: PlutusDatumSchema,
) -> Result<PlutusData, JsError> {
use serde_json::Value;
fn encode_number(x: serde_json::Number) -> Result<PlutusData, JsError> {
if let Some(x) = x.as_u64() {
Ok(PlutusData::new_integer(&BigInt::from(x)))
} else if let Some(x) = x.as_i64() {
Ok(PlutusData::new_integer(&BigInt::from(x)))
} else {
Err(JsError::from_str("floats not allowed in plutus datums"))
}
}
fn encode_string(
s: &str,
schema: PlutusDatumSchema,
is_key: bool,
) -> Result<PlutusData, JsError> {
if schema == PlutusDatumSchema::BasicConversions {
if s.starts_with("0x") {
// this must be a valid hex bytestring after
hex::decode(&s[2..])
.map(|bytes| PlutusData::new_bytes(bytes))
.map_err(|err| JsError::from_str(&format!("Error decoding {}: {}", s, err)))
} else if is_key {
// try as an integer
BigInt::from_str(s)
.map(|x| PlutusData::new_integer(&x))
// if not, we use the utf8 bytes of the string instead directly
.or_else(|_err| Ok(PlutusData::new_bytes(s.as_bytes().to_vec())))
} else {
// can only be UTF bytes if not in a key and not prefixed by 0x
Ok(PlutusData::new_bytes(s.as_bytes().to_vec()))
}
} else {
if s.starts_with("0x") {
Err(JsError::from_str("Hex byte strings in detailed schema should NOT start with 0x and should just contain the hex characters"))
} else {
hex::decode(s)
.map(|bytes| PlutusData::new_bytes(bytes))
.map_err(|e| JsError::from_str(&e.to_string()))
}
}
}
fn encode_array(
json_arr: Vec<Value>,
schema: PlutusDatumSchema,
) -> Result<PlutusData, JsError> {
let mut arr = PlutusList::new();
for value in json_arr {
arr.add(&encode_json_value_to_plutus_datum(value, schema)?);
}
Ok(PlutusData::new_list(&arr))
}
match schema {
PlutusDatumSchema::BasicConversions => match value {
Value::Null => Err(JsError::from_str("null not allowed in plutus datums")),
Value::Bool(_) => Err(JsError::from_str("bools not allowed in plutus datums")),
Value::Number(x) => encode_number(x),
// no strings in plutus so it's all bytes (as hex or utf8 printable)
Value::String(s) => encode_string(&s, schema, false),
Value::Array(json_arr) => encode_array(json_arr, schema),
Value::Object(json_obj) => {
let mut map = PlutusMap::new();
for (raw_key, raw_value) in json_obj {
let key = encode_string(&raw_key, schema, true)?;
let value = encode_json_value_to_plutus_datum(raw_value, schema)?;
map.insert(&key, &value);
}
Ok(PlutusData::new_map(&map))
}
},
PlutusDatumSchema::DetailedSchema => match value {
Value::Object(obj) => {
if obj.len() == 1 {
// all variants except tagged constructors
let (k, v) = obj.into_iter().next().unwrap();
fn tag_mismatch() -> JsError {
JsError::from_str("key does not match type")
}
match k.as_str() {
"int" => match v {
Value::Number(x) => encode_number(x),
_ => Err(tag_mismatch()),
},
"bytes" => {
encode_string(v.as_str().ok_or_else(tag_mismatch)?, schema, false)
}
"list" => {
encode_array(v.as_array().ok_or_else(tag_mismatch)?.clone(), schema)
}
"map" => {
let mut map = PlutusMap::new();
fn map_entry_err() -> JsError {
JsError::from_str("entry format in detailed schema map object not correct. Needs to be of form {\"k\": {\"key_type\": key}, \"v\": {\"value_type\", value}}")
}
for entry in v.as_array().ok_or_else(tag_mismatch)? {
let entry_obj = entry.as_object().ok_or_else(map_entry_err)?;
let raw_key = entry_obj.get("k").ok_or_else(map_entry_err)?;
let value = entry_obj.get("v").ok_or_else(map_entry_err)?;
let key =
encode_json_value_to_plutus_datum(raw_key.clone(), schema)?;
map.insert(
&key,
&encode_json_value_to_plutus_datum(value.clone(), schema)?,
);
}
Ok(PlutusData::new_map(&map))
}
invalid_key => Err(JsError::from_str(&format!(
"key '{}' in tagged object not valid",
invalid_key
))),
}
} else {
// constructor with tagged variant
if obj.len() != 2 {
return Err(JsError::from_str("detailed schemas must either have only one of the following keys: \"int\", \"bytes\", \"list\" or \"map\", or both of these 2 keys: \"constructor\" + \"fields\""));
}
let variant: BigNum = obj
.get("constructor")
.and_then(|v| Some(to_bignum(v.as_u64()?)))
.ok_or_else(|| JsError::from_str("tagged constructors must contain an unsigned integer called \"constructor\""))?;
let fields_json =
obj.get("fields")
.and_then(|f| f.as_array())
.ok_or_else(|| {
JsError::from_str(
"tagged constructors must contian a list called \"fields\"",
)
})?;
let mut fields = PlutusList::new();
for field_json in fields_json {
let field = encode_json_value_to_plutus_datum(field_json.clone(), schema)?;
fields.add(&field);
}
Ok(PlutusData::new_constr_plutus_data(&ConstrPlutusData::new(
&variant, &fields,
)))
}
}
_ => Err(JsError::from_str(&format!(
"DetailedSchema requires ALL JSON to be tagged objects, found: {}",
value
))),
},
}
}
pub fn get(&self, key: &PlutusData) -> Option<PlutusData>
pub fn keys(&self) -> PlutusList
Trait Implementations§
source§impl Deserialize for PlutusMap
impl Deserialize for PlutusMap
fn deserialize<R: BufRead + Seek>(
raw: &mut Deserializer<R>
) -> Result<Self, DeserializeError>
source§impl Ord for PlutusMap
impl Ord for PlutusMap
source§impl PartialEq<PlutusMap> for PlutusMap
impl PartialEq<PlutusMap> for PlutusMap
source§impl PartialOrd<PlutusMap> for PlutusMap
impl PartialOrd<PlutusMap> for PlutusMap
1.0.0 · source§fn le(&self, other: &Rhs) -> bool
fn le(&self, other: &Rhs) -> bool
This method tests less than or equal to (for
self
and other
) and is used by the <=
operator. Read more