diff --git a/Cargo.toml b/Cargo.toml index 31b5c8c..9cc5a3c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -71,7 +71,6 @@ exporters = ["dep:handlebars"] inspector = ["dep:crossterm", "dep:ratatui", "dep:tui-textarea", "cli"] postgres = ["dep:postgres"] sqlite = ["dep:rusqlite"] -json-bin = [] [package.metadata.release] tag-prefix = "" diff --git a/src/compiler/generator.rs b/src/compiler/generator.rs index cfed3f0..fd65de6 100644 --- a/src/compiler/generator.rs +++ b/src/compiler/generator.rs @@ -1864,7 +1864,7 @@ pub(crate) fn reduce_toplevel( | Token::DefunAlias(..) | Token::DefConsts(..) => Ok(None), Token::DefPermutation { from, to, signs } => { - let froms = from + let froms: Vec = from .iter() .map(|from| { if let Some(n) = reduce(from, ctx, settings)? { @@ -1907,16 +1907,16 @@ pub(crate) fn reduce_toplevel( signs: signs.clone(), }, )?; - + // Determine suitably unique name for the permutation + // constraint. + let name = format!( + "{}_intrld_{}", + froms.iter().map(|f| f.as_handle().mangled_name()).join("_"), + tos.iter().map(|f| f.as_handle().mangled_name()).join("_"), + ); + // Done Ok(Some(Constraint::Permutation { - handle: Handle::new( - ctx.module(), - format!( - "{}_intrld_{}", - froms.iter().map(|f| f.to_string()).join("_"), - tos.iter().map(|f| f.to_string()).join("_"), - ), - ), + handle: Handle::new(ctx.module(), name), from: froms, to: tos, })) diff --git a/src/compiler/node.rs b/src/compiler/node.rs index bd11d8c..c39560f 100644 --- a/src/compiler/node.rs +++ b/src/compiler/node.rs @@ -4,7 +4,8 @@ use cached::Cached; use num_bigint::BigInt; use num_traits::{One, ToPrimitive, Zero}; use owo_colors::{colored::Color, OwoColorize}; -use serde::{Deserialize, Serialize}; +use serde::de::{Error, Visitor}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::write; use std::{ collections::HashSet, @@ -17,7 +18,7 @@ use crate::structs::Handle; use super::{ConstraintSet, Domain, EvalSettings, Intrinsic, Kind, Magma, Type}; -#[derive(Clone, Deserialize, Debug, Eq)] +#[derive(Clone, Debug, Eq)] pub struct ColumnRef { h: Option, id: Option, @@ -156,33 +157,45 @@ impl From for ColumnRef { } } -#[cfg(feature = "json-bin")] impl Serialize for ColumnRef { - fn serialize(&self, serializer: S) -> Result { + fn serialize(&self, serializer: S) -> Result { let fmt_str = match (&self.h, &self.id) { (None, None) => unreachable!(), - (Some(h), None) => format!("{}", h.to_serialize_string()), + (Some(h), None) => format!("{}", h.to_serialized_string()), (None, Some(id)) => format!("#{}", id), - (Some(h), Some(id)) => format!("{}#{}", h.to_serialize_string(), id), + (Some(h), Some(id)) => format!("{}#{}", h.to_serialized_string(), id), }; // Done serializer.serialize_str(&fmt_str) } } -#[cfg(not(feature = "json-bin"))] -use serde::ser::SerializeStruct; - -#[cfg(not(feature = "json-bin"))] -impl Serialize for ColumnRef { - fn serialize(&self, serializer: S) -> Result - where - S: serde::ser::Serializer, - { - let mut handle = serializer.serialize_struct("ColumnRef", 2)?; - handle.serialize_field("h", &self.h)?; - handle.serialize_field("id", &self.id)?; - handle.end() +impl<'a> Deserialize<'a> for ColumnRef { + fn deserialize>(deserializer: S) -> Result { + let st = String::deserialize(deserializer)?; + // Split out column/register index + let p1: Vec<&str> = st.split("#").collect(); + // + match p1.len() { + 1 => { + // Parse the handle itself + let h = Handle::from_serialized_string(p1[0]).map_err(S::Error::custom)?; + // Done + std::result::Result::Ok(ColumnRef::from_handle(h)) + } + 2 => { + // Parser the column ID (or report error) + let id: ColumnID = p1[1].parse().map_err(S::Error::custom)?; + // Parse the handle itself + let h = Handle::from_serialized_string(p1[0]).map_err(S::Error::custom)?; + // Done + std::result::Result::Ok(ColumnRef::from_handle(h).id(id)) + } + _ => { + let msg = format!("invalid serialized ColumnRef: {}", st); + Err(S::Error::custom(msg)) + } + } } } diff --git a/src/main.rs b/src/main.rs index b121e4f..3ddcf9e 100755 --- a/src/main.rs +++ b/src/main.rs @@ -952,14 +952,10 @@ fn main() -> Result<()> { std::fs::File::create(&outfile) .with_context(|| format!("while creating `{}`", &outfile))? .write_all( - if json && cfg!(feature = "json-bin") { - if pretty { - serde_json::to_string_pretty(&constraints)? - } else { - serde_json::to_string(&constraints)? - } + if json && pretty { + serde_json::to_string_pretty(&constraints)? } else if json { - panic!("Exporting as JSON requires the `json-bin` feature."); + serde_json::to_string(&constraints)? } else if pretty { ron::ser::to_string_pretty(&constraints, ron::ser::PrettyConfig::default())? } else { diff --git a/src/structs/handle.rs b/src/structs/handle.rs index 445af15..d0f261f 100644 --- a/src/structs/handle.rs +++ b/src/structs/handle.rs @@ -1,11 +1,13 @@ -use serde::{Deserialize, Serialize}; +use serde::de::{Error, Visitor}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::fmt; use crate::{compiler::MAIN_MODULE, utils::purify}; use super::{ARRAY_SEPARATOR, MODULE_SEPARATOR}; /// A handle uniquely and absolutely defines a symbol -#[derive(Clone, Deserialize)] +#[derive(Clone)] pub struct Handle { /// the module to which the symbol belongs /// NOTE multi-level paths are not yet implemented @@ -189,51 +191,45 @@ impl std::fmt::Display for Handle { } } -#[cfg(feature = "json-bin")] impl Handle { - pub fn to_serialize_string(&self) -> String { - // Sanity checks - assert!( - !self.module.contains(":"), - "JSON deserisalisation conflict on module" - ); - assert!( - !self.name.contains(":"), - "JSON deserisalisation conflict on name" - ); - assert!( - !self.perspective.as_ref().map_or(false, |s| s.contains(":")), - "JSON deserisalisation conflict on perspective" - ); - // + pub fn to_serialized_string(&self) -> String { match &self.perspective { - None => format!("{}:{}", self.module, self.name), - Some(p) => format!("{}:{}:{}", self.module, self.name, p), + None => format!("{}.{}", self.module, self.name), + Some(p) => format!("{}.{}:{}", self.module, self.name, p), + } + } + pub fn from_serialized_string(input: &str) -> Result { + let p1: Vec<&str> = input.split(":").collect(); + // Split up module / name + let p2: Vec<&str> = p1[0].split(".").collect(); + // Error check + if p1.len() > 2 || p2.len() > 2 { + Err(format!("invalid serialized Handle: {}", input)) + } else { + // Attempt to extract perspective (if present) + let perspective = if p1.len() == 1 { + // No perspective provided + None + } else { + // Extract perspective name + Some(p1[1].to_string()) + }; + // Done + Ok(Handle::maybe_with_perspective(p2[0], p2[1], perspective)) } } } -#[cfg(feature = "json-bin")] -impl Serialize for Handle { - fn serialize(&self, serializer: S) -> Result { - // Done - serializer.serialize_str(&self.to_serialize_string()) +impl<'a> Deserialize<'a> for Handle { + fn deserialize>(deserializer: S) -> Result { + let st = String::deserialize(deserializer)?; + // Decode it + Self::from_serialized_string(&st).map_err(S::Error::custom) } } -#[cfg(not(feature = "json-bin"))] -use serde::ser::SerializeStruct; - -#[cfg(not(feature = "json-bin"))] impl Serialize for Handle { - fn serialize(&self, serializer: S) -> Result - where - S: serde::ser::Serializer, - { - let mut handle = serializer.serialize_struct("Handle", 3)?; - handle.serialize_field("module", &self.module)?; - handle.serialize_field("name", &self.name)?; - handle.serialize_field("perspective", &self.perspective)?; - handle.end() + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&self.to_serialized_string()) } }