use std::io::{Read, Write};
use base64::{Engine as _, engine::general_purpose::URL_SAFE_NO_PAD};
use flate2::{Compression, read::GzDecoder, write::GzEncoder};
use crate::{ConversionError, deserialize_ast, serialize_ast_compact};
use cp_ast_core::operation::AstEngine;
#[must_use = "share-state encoding can fail and the result should be handled"]
pub fn encode_share_state_json(document_json: &str) -> Result<String, ConversionError> {
let engine = deserialize_ast(document_json)?;
let canonical_json = serialize_ast_compact(&engine)?;
let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
encoder
.write_all(canonical_json.as_bytes())
.map_err(|err| ConversionError::Gzip(err.to_string()))?;
let compressed = encoder
.finish()
.map_err(|err| ConversionError::Gzip(err.to_string()))?;
Ok(URL_SAFE_NO_PAD.encode(compressed))
}
#[must_use = "share-state decoding can fail and the result should be handled"]
pub fn decode_share_state_json(state: &str) -> Result<String, ConversionError> {
let compressed = URL_SAFE_NO_PAD
.decode(state)
.map_err(|err| ConversionError::Base64(err.to_string()))?;
let mut decoder = GzDecoder::new(compressed.as_slice());
let mut json = String::new();
decoder
.read_to_string(&mut json)
.map_err(|err| ConversionError::Gzip(err.to_string()))?;
let engine = deserialize_ast(&json)?;
serialize_ast_compact(&engine)
}
#[must_use = "share-state deserialization can fail and the result should be handled"]
pub fn deserialize_share_state(state: &str) -> Result<AstEngine, ConversionError> {
let json = decode_share_state_json(state)?;
deserialize_ast(&json)
}