#![allow(clippy::should_implement_trait)]
use std::sync::Arc;
use serde_json::Value;
use super::model::{BNode, BNodeRange, BSlice};
use crate::dynamic::{
types::{Dyn, DynamicMark, DynamicNode, DynamicNodeType},
DynamicSchema,
};
use crate::model::{Fragment, MarkSet, Slice};
use crate::transform::{
map::{MapResult, Mappable, Mapping, StepMap},
structure::{
can_join, can_split, drop_point, find_wrapping, insert_point, join_point, lift_target,
},
AddMarkStep, AddNodeMarkStep, AttrStep, DocAttrStep, MarkOrType, RemoveMarkStep,
RemoveNodeMarkStep, ReplaceAroundStep, ReplaceStep, Span, Step, Transform, Wrapper,
};
pub struct BStepMap {
pub inner: StepMap,
}
impl BStepMap {
pub fn new(ranges: Vec<usize>) -> Self {
BStepMap {
inner: StepMap::new(ranges),
}
}
pub fn ranges(&self) -> &[usize] {
&self.inner.ranges
}
pub fn map(&self, pos: usize, assoc: i32) -> usize {
self.inner.map(pos, assoc)
}
pub fn map_result(&self, pos: usize, assoc: i32) -> BMapResult {
BMapResult {
inner: self.inner.map_result(pos, assoc),
}
}
pub fn recover(&self, value: usize) -> Option<usize> {
self.inner.recover(value)
}
pub fn invert(&self) -> BStepMap {
BStepMap {
inner: self.inner.invert(),
}
}
pub fn for_each<F: FnMut(usize, usize, usize, usize)>(&self, f: F) {
self.inner.for_each(f)
}
pub fn offset(n: isize) -> BStepMap {
BStepMap {
inner: StepMap::offset(n),
}
}
pub fn empty_map() -> BStepMap {
BStepMap {
inner: StepMap::empty(),
}
}
}
pub struct BMapResult {
pub inner: MapResult,
}
impl BMapResult {
pub fn pos(&self) -> usize {
self.inner.pos
}
pub fn deleted(&self) -> bool {
self.inner.deleted()
}
pub fn deleted_before(&self) -> bool {
self.inner.deleted_before()
}
pub fn deleted_after(&self) -> bool {
self.inner.deleted_after()
}
pub fn deleted_across(&self) -> bool {
self.inner.deleted_across()
}
pub fn recover(&self) -> Option<usize> {
self.inner.recover
}
}
pub struct BMapping {
pub inner: Mapping,
}
impl BMapping {
pub fn new() -> Self {
BMapping {
inner: Mapping::new(),
}
}
pub fn maps(&self) -> Vec<BStepMap> {
self.inner
.maps
.iter()
.map(|m| BStepMap { inner: m.clone() })
.collect()
}
pub fn to_end(&self) -> usize {
self.inner.to
}
pub fn map(&self, pos: usize, assoc: i32) -> usize {
self.inner.map(pos, assoc)
}
pub fn map_result(&self, pos: usize, assoc: i32) -> BMapResult {
BMapResult {
inner: self.inner.map_result(pos, assoc),
}
}
pub fn append_map(&mut self, map: BStepMap, mirrors: Option<usize>) {
self.inner.append_map(map.inner, mirrors);
}
pub fn append_mapping(&mut self, other: &BMapping) {
self.inner.append_mapping(&other.inner);
}
pub fn append_mapping_inverted(&mut self, other: &BMapping) {
self.inner.append_mapping_inverted(&other.inner);
}
pub fn get_mirror(&self, n: usize) -> Option<usize> {
self.inner.get_mirror(n)
}
pub fn set_mirror(&mut self, n: usize, m: usize) {
self.inner.set_mirror(n, m);
}
pub fn invert(&self) -> BMapping {
BMapping {
inner: self.inner.invert(),
}
}
pub fn copy(&self) -> BMapping {
BMapping {
inner: self.inner.clone(),
}
}
pub fn slice(&self, from: usize, to: Option<usize>) -> BMapping {
BMapping {
inner: self.inner.slice(from, to),
}
}
}
impl Default for BMapping {
fn default() -> Self {
Self::new()
}
}
pub struct BStep {
pub inner: Step<Dyn>,
}
impl BStep {
pub fn from_json(schema: &Arc<DynamicSchema>, val: Value) -> Result<BStep, String> {
schema
.with_types(|| serde_json::from_value(val))
.map(|inner| BStep { inner })
.map_err(|e| format!("{e:?}"))
}
pub fn to_json(&self) -> Value {
serde_json::to_value(&self.inner).unwrap_or(Value::Null)
}
pub fn apply(&self, doc: &BNode) -> Result<BNode, String> {
doc.schema
.with_types(|| self.inner.apply(&doc.inner))
.map(|n| BNode {
schema: doc.schema.clone(),
inner: n,
})
.map_err(|e| format!("{e:?}"))
}
pub fn get_map(&self) -> BStepMap {
BStepMap {
inner: self.inner.get_map(),
}
}
pub fn invert(&self, doc: &BNode) -> BStep {
BStep {
inner: doc.schema.with_types(|| self.inner.invert(&doc.inner)),
}
}
pub fn map_through(&self, mapping: &BMapping) -> Option<BStep> {
self.inner.map(&mapping.inner).map(|s| BStep { inner: s })
}
pub fn merge_with(&self, other: &BStep) -> Option<BStep> {
self.inner.merge(&other.inner).map(|s| BStep { inner: s })
}
pub fn make_replace(from: usize, to: usize, slice: Slice<Dyn>, structure: bool) -> BStep {
BStep {
inner: Step::Replace(ReplaceStep {
span: Span { from, to },
slice,
structure,
}),
}
}
pub fn make_replace_around(
from: usize,
to: usize,
gap_from: usize,
gap_to: usize,
slice: Slice<Dyn>,
insert: usize,
structure: bool,
) -> BStep {
BStep {
inner: Step::ReplaceAround(ReplaceAroundStep {
span: Span { from, to },
gap_from,
gap_to,
slice,
insert,
structure,
}),
}
}
pub fn make_add_mark(from: usize, to: usize, mark: DynamicMark) -> BStep {
BStep {
inner: Step::AddMark(AddMarkStep {
span: Span { from, to },
mark,
}),
}
}
pub fn make_remove_mark(from: usize, to: usize, mark: DynamicMark) -> BStep {
BStep {
inner: Step::RemoveMark(RemoveMarkStep {
span: Span { from, to },
mark,
}),
}
}
pub fn make_add_node_mark(pos: usize, mark: DynamicMark) -> BStep {
BStep {
inner: Step::AddNodeMark(AddNodeMarkStep { pos, mark }),
}
}
pub fn make_remove_node_mark(pos: usize, mark: DynamicMark) -> BStep {
BStep {
inner: Step::RemoveNodeMark(RemoveNodeMarkStep { pos, mark }),
}
}
pub fn make_attr(pos: usize, attr: String, value: Value) -> BStep {
BStep {
inner: Step::Attr(AttrStep { pos, attr, value }),
}
}
pub fn make_doc_attr(attr: String, value: Value) -> BStep {
BStep {
inner: Step::DocAttr(DocAttrStep { attr, value }),
}
}
}
pub struct BStepResult {
pub schema: Arc<DynamicSchema>,
pub doc: Option<DynamicNode>,
pub failed: Option<String>,
}
pub fn wrap_step_result(
schema: Arc<DynamicSchema>,
result: Result<DynamicNode, impl std::fmt::Debug>,
) -> BStepResult {
match result {
Ok(doc) => BStepResult {
schema,
doc: Some(doc),
failed: None,
},
Err(e) => BStepResult {
schema,
doc: None,
failed: Some(format!("{e:?}")),
},
}
}
pub struct BTransform {
pub schema: Arc<DynamicSchema>,
pub inner: Transform<Dyn>,
}
impl BTransform {
pub fn new(doc: &BNode) -> Self {
let schema = doc.schema.clone();
let inner = schema.with_types(|| Transform::new(doc.inner.clone()));
BTransform { schema, inner }
}
pub fn doc(&self) -> BNode {
BNode {
schema: self.schema.clone(),
inner: self.inner.doc.clone(),
}
}
pub fn before(&self) -> BNode {
BNode {
schema: self.schema.clone(),
inner: self.inner.before().clone(),
}
}
pub fn steps(&self) -> Vec<BStep> {
self.inner
.steps
.iter()
.map(|s| BStep { inner: s.clone() })
.collect()
}
pub fn docs(&self) -> Vec<BNode> {
self.inner
.docs
.iter()
.map(|d| BNode {
schema: self.schema.clone(),
inner: d.clone(),
})
.collect()
}
pub fn mapping(&self) -> BMapping {
BMapping {
inner: self.inner.mapping.clone(),
}
}
pub fn doc_changed(&self) -> bool {
self.inner.doc_changed()
}
pub fn step(&mut self, step: &BStep) -> Result<(), String> {
let schema = Arc::clone(&self.schema);
schema
.with_types(|| self.inner.step(step.inner.clone()))
.map_err(|e| format!("{e:?}"))
.map(|_| ())
}
pub fn maybe_step(&mut self, step: &BStep) -> Option<String> {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.maybe_step(step.inner.clone()))
}
pub fn changed_range(&self) -> Option<(usize, usize)> {
self.inner.changed_range()
}
pub fn replace(&mut self, from: usize, to: Option<usize>, slice: Option<Slice<Dyn>>) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.replace(from, to, slice));
}
pub fn replace_with(&mut self, from: usize, to: usize, content: Fragment<Dyn>) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.replace_with(from, to, content));
}
pub fn delete(&mut self, from: usize, to: usize) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.delete(from, to));
}
pub fn insert(&mut self, pos: usize, content: Fragment<Dyn>) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.insert(pos, content));
}
pub fn add_mark(&mut self, from: usize, to: usize, mark: DynamicMark) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.add_mark(from, to, mark));
}
pub fn remove_mark(&mut self, from: usize, to: usize, mark: Option<MarkOrType<Dyn>>) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.remove_mark(from, to, mark));
}
pub fn add_node_mark(&mut self, pos: usize, mark: DynamicMark) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.add_node_mark(pos, mark));
}
pub fn remove_node_mark(&mut self, pos: usize, mark: MarkOrType<Dyn>) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.remove_node_mark(pos, mark));
}
pub fn replace_range(&mut self, from: usize, to: usize, slice: Slice<Dyn>) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.replace_range(from, to, slice));
}
pub fn replace_range_with(&mut self, from: usize, to: usize, node: DynamicNode) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.replace_range_with(from, to, node));
}
pub fn delete_range(&mut self, from: usize, to: usize) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.delete_range(from, to));
}
pub fn lift(&mut self, range: &BNodeRange, target: usize) -> Result<(), String> {
let schema = Arc::clone(&self.schema);
schema.with_types(|| {
let node_range = range
.to_node_range()
.ok_or_else(|| "invalid range".to_string())?;
self.inner.lift(&node_range, target);
Ok(())
})
}
pub fn wrap(&mut self, range: &BNodeRange, wrappers: Vec<Wrapper<Dyn>>) -> Result<(), String> {
let schema = Arc::clone(&self.schema);
schema.with_types(|| {
let node_range = range
.to_node_range()
.ok_or_else(|| "invalid range".to_string())?;
self.inner.wrap(&node_range, &wrappers);
Ok(())
})
}
pub fn split(
&mut self,
pos: usize,
depth: Option<usize>,
types_after: Option<&[DynamicNodeType]>,
) -> Result<(), String> {
let schema = Arc::clone(&self.schema);
schema
.with_types(|| self.inner.split(pos, depth, types_after))
.map_err(|e| format!("{e:?}"))
.map(|_| ())
}
pub fn join(&mut self, pos: usize, depth: Option<usize>) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.join(pos, depth));
}
pub fn set_block_type(
&mut self,
from: usize,
to: usize,
type_: DynamicNodeType,
attrs: Option<Value>,
) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.set_block_type(from, to, type_, attrs));
}
pub fn set_node_markup(
&mut self,
pos: usize,
type_: Option<DynamicNodeType>,
attrs: Option<Value>,
marks: Option<MarkSet<Dyn>>,
) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.set_node_markup(pos, type_, attrs, marks));
}
pub fn set_node_attribute(&mut self, pos: usize, attr: String, value: Value) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.set_node_attribute(pos, &attr, value));
}
pub fn set_doc_attribute(&mut self, attr: String, value: Value) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| self.inner.set_doc_attribute(&attr, value));
}
pub fn clear_incompatible(
&mut self,
pos: usize,
type_: &super::model::BNodeType,
clear_newlines: bool,
) {
let schema = Arc::clone(&self.schema);
schema.with_types(|| {
self.inner
.clear_incompatible(pos, type_.inner, None, clear_newlines)
});
}
}
pub fn b_lift_target(range: &BNodeRange) -> Option<usize> {
range.schema.with_types(|| {
let node_range = range.to_node_range()?;
lift_target(&node_range)
})
}
pub fn b_find_wrapping(
range: &BNodeRange,
node_type: DynamicNodeType,
pred: impl Fn(DynamicNodeType) -> bool,
) -> Option<Vec<Wrapper<Dyn>>> {
range.schema.with_types(|| {
let node_range = range.to_node_range()?;
find_wrapping(&node_range, node_type, |t: &DynamicNodeType| pred(*t))
})
}
pub fn b_can_split(
doc: &BNode,
pos: usize,
depth: Option<usize>,
types_after: Option<&[DynamicNodeType]>,
) -> bool {
doc.schema
.with_types(|| can_split::<Dyn>(&doc.inner, pos, depth, types_after))
}
pub fn b_can_join(doc: &BNode, pos: usize) -> bool {
doc.schema
.with_types(|| can_join::<Dyn>(&doc.inner, pos).unwrap_or(false))
}
pub fn b_join_point(doc: &BNode, pos: usize, dir: Option<i32>) -> Option<usize> {
doc.schema
.with_types(|| join_point::<Dyn>(&doc.inner, pos, dir))
}
pub fn b_insert_point(doc: &BNode, pos: usize, node_type: DynamicNodeType) -> Option<usize> {
doc.schema
.with_types(|| insert_point::<Dyn>(&doc.inner, pos, node_type))
}
pub fn b_drop_point(doc: &BNode, pos: usize, slice: &BSlice) -> Option<usize> {
doc.schema
.with_types(|| drop_point::<Dyn>(&doc.inner, pos, &slice.inner))
}