1use qualname::{NcName, QName};
4use std::cmp::Ordering;
5use std::rc::Rc;
6use url::Url;
7
8use english_numbers::{Formatting, convert};
9use formato::Formato;
10use italian_numbers::roman_converter;
11
12use crate::item::{Item, Node, NodeType, Sequence, SequenceTrait};
13use crate::pattern::{Branch, Pattern, Step};
14use crate::transform::context::{Context, StaticContext};
15use crate::transform::{
16 ArithmeticOperand, ArithmeticOperator, Axis, KindTest, NameTest, NodeTest, Transform,
17};
18use crate::value::Value;
19use crate::xdmerror::{Error, ErrorKind};
20
21#[derive(Copy, Clone, Debug, Default, PartialEq)]
23pub enum Level {
24 #[default]
25 Single,
26 Multiple,
27 Any,
28}
29
30#[derive(Clone, Debug)]
32pub struct Numbering<N: Node> {
33 level: Level,
34 count: Option<Pattern<N>>,
35 from: Option<Pattern<N>>,
36}
37impl<N: Node> Numbering<N> {
38 pub fn new(level: Level, count: Option<Pattern<N>>, from: Option<Pattern<N>>) -> Self {
39 Numbering { level, count, from }
40 }
41}
42
43pub fn generate_integers<
45 N: Node,
46 F: FnMut(&str) -> Result<(), Error>,
47 G: FnMut(&str) -> Result<N, Error>,
48 H: FnMut(&Url) -> Result<String, Error>,
49>(
50 ctxt: &Context<N>,
51 stctxt: &mut StaticContext<N, F, G, H>,
52 _start_at: &Transform<N>,
53 select: &Transform<N>,
54 num: &Numbering<N>,
55) -> Result<Sequence<N>, Error> {
56 if num.level != Level::Single {
58 return Err(Error::new(
59 ErrorKind::NotImplemented,
60 "only single level is implemented",
61 ));
62 }
63
64 let n = ctxt.dispatch(stctxt, select)?;
66 if n.len() == 1 {
67 if let Item::Node(m) = &n[0] {
68 let count_pat = (num.count)
70 .clone()
71 .unwrap_or(Pattern::Selection(Branch::SingleStep(
72 match m.node_type() {
73 NodeType::Element => Step::new(
74 Axis::SelfAxis,
75 Axis::SelfAxis,
76 NodeTest::Name(NameTest::Name(m.name().unwrap())),
77 ),
78 NodeType::Text => Step::new(
79 Axis::SelfAxis,
80 Axis::SelfAxis,
81 NodeTest::Kind(KindTest::Text),
82 ),
83 _ => {
84 return Err(Error::new(
85 ErrorKind::TypeError,
86 "cannot match this type of node",
87 ));
88 }
89 },
90 )));
91
92 let a = if count_pat.matches(ctxt, stctxt, &Item::Node(m.clone())) {
95 vec![m.clone()]
96 } else {
97 m.ancestor_iter()
98 .filter(|i| count_pat.matches(ctxt, stctxt, &Item::Node(i.clone())))
99 .take(1)
100 .collect()
101 };
102 if a.is_empty() {
103 return Ok(vec![]);
104 }
105 let f: Vec<N> = if let Some(fr) = &num.from.clone() {
108 m.ancestor_iter()
109 .filter(|i| {
110 if i.node_type() == NodeType::Document {
111 true
112 } else {
113 fr.matches(ctxt, stctxt, &Item::Node(i.clone()))
114 }
115 })
116 .take(1)
117 .collect()
118 } else {
119 vec![m.owner_document().clone()]
121 };
122 if f.is_empty() {
123 return Ok(vec![]);
124 }
125 let af_test: Vec<N> = if a[0].is_same(&f[0]) {
127 vec![a[0].clone()]
128 } else {
129 a[0].ancestor_iter().filter(|i| i.is_same(&f[0])).collect()
130 };
131 let af = if af_test.is_empty() { vec![] } else { a };
132 if af.is_empty() {
133 return Ok(vec![]);
134 }
135 let result: Vec<N> = af[0]
137 .prev_iter()
138 .filter(|i| count_pat.matches(ctxt, stctxt, &Item::Node(i.clone())))
139 .collect();
140 Ok(vec![Item::Value(Rc::new(Value::from(1 + result.len())))])
141 } else {
142 Err(Error::new_with_code(
143 ErrorKind::TypeError,
144 "not a singleton node",
145 Some(QName::from_local_name(
146 NcName::try_from("XTTE1000").unwrap(),
147 )),
148 ))
149 }
150 } else {
151 Err(Error::new_with_code(
152 ErrorKind::TypeError,
153 "not a singleton node",
154 Some(QName::from_local_name(
155 NcName::try_from("XTTE1000").unwrap(),
156 )),
157 ))
158 }
159}
160
161pub fn number<
163 N: Node,
164 F: FnMut(&str) -> Result<(), Error>,
165 G: FnMut(&str) -> Result<N, Error>,
166 H: FnMut(&Url) -> Result<String, Error>,
167>(
168 ctxt: &Context<N>,
169 stctxt: &mut StaticContext<N, F, G, H>,
170 num: &Transform<N>,
171) -> Result<Sequence<N>, Error> {
172 let n = ctxt.dispatch(stctxt, num)?;
173 match n.len() {
174 1 => {
175 match n[0].to_int() {
177 Ok(i) => Ok(vec![Item::Value(Rc::new(Value::from(i)))]),
178 _ => {
179 Ok(vec![Item::Value(Rc::new(Value::from(n[0].to_double())))])
182 }
183 }
184 }
185 _ => Err(Error::new(
186 ErrorKind::TypeError,
187 String::from("not a singleton sequence"),
188 )),
189 }
190}
191
192pub fn sum<
194 N: Node,
195 F: FnMut(&str) -> Result<(), Error>,
196 G: FnMut(&str) -> Result<N, Error>,
197 H: FnMut(&Url) -> Result<String, Error>,
198>(
199 ctxt: &Context<N>,
200 stctxt: &mut StaticContext<N, F, G, H>,
201 s: &Transform<N>,
202) -> Result<Sequence<N>, Error> {
203 Ok(vec![Item::Value(Rc::new(Value::from(
204 ctxt.dispatch(stctxt, s)?.iter().fold(0.0, |mut acc, i| {
205 acc += i.to_double();
206 acc
207 }),
208 )))])
209}
210
211pub fn avg<
213 N: Node,
214 F: FnMut(&str) -> Result<(), Error>,
215 G: FnMut(&str) -> Result<N, Error>,
216 H: FnMut(&Url) -> Result<String, Error>,
217>(
218 ctxt: &Context<N>,
219 stctxt: &mut StaticContext<N, F, G, H>,
220 s: &Transform<N>,
221) -> Result<Sequence<N>, Error> {
222 let seq = ctxt.dispatch(stctxt, s)?;
223 if seq.is_empty() {
224 return Ok(seq);
225 }
226
227 let sum = seq.iter().fold(0.0, |mut acc, i| {
229 acc += i.to_double();
230 acc
231 });
232 Ok(vec![Item::Value(Rc::new(Value::from(
233 sum / (seq.len() as f64),
234 )))])
235}
236
237pub fn min<
239 N: Node,
240 F: FnMut(&str) -> Result<(), Error>,
241 G: FnMut(&str) -> Result<N, Error>,
242 H: FnMut(&Url) -> Result<String, Error>,
243>(
244 ctxt: &Context<N>,
245 stctxt: &mut StaticContext<N, F, G, H>,
246 s: &Transform<N>,
247) -> Result<Sequence<N>, Error> {
248 let seq = ctxt.dispatch(stctxt, s)?;
249 if seq.is_empty() {
251 Ok(seq)
252 } else {
253 Ok(vec![Item::Value(Rc::new(Value::from(
254 seq.iter().skip(1).fold(seq[0].to_double(), |acc, i| {
255 if acc > i.to_double() {
256 i.to_double()
257 } else {
258 acc
259 }
260 }),
261 )))])
262 }
263}
264
265pub fn max<
267 N: Node,
268 F: FnMut(&str) -> Result<(), Error>,
269 G: FnMut(&str) -> Result<N, Error>,
270 H: FnMut(&Url) -> Result<String, Error>,
271>(
272 ctxt: &Context<N>,
273 stctxt: &mut StaticContext<N, F, G, H>,
274 s: &Transform<N>,
275) -> Result<Sequence<N>, Error> {
276 let seq = ctxt.dispatch(stctxt, s)?;
277 if seq.is_empty() {
279 Ok(seq)
280 } else {
281 Ok(vec![Item::Value(Rc::new(Value::from(
282 seq.iter().skip(1).fold(seq[0].to_double(), |acc, i| {
283 if acc < i.to_double() {
284 i.to_double()
285 } else {
286 acc
287 }
288 }),
289 )))])
290 }
291}
292
293pub fn floor<
295 N: Node,
296 F: FnMut(&str) -> Result<(), Error>,
297 G: FnMut(&str) -> Result<N, Error>,
298 H: FnMut(&Url) -> Result<String, Error>,
299>(
300 ctxt: &Context<N>,
301 stctxt: &mut StaticContext<N, F, G, H>,
302 f: &Transform<N>,
303) -> Result<Sequence<N>, Error> {
304 let n = ctxt.dispatch(stctxt, f)?;
305 match n.len() {
306 1 => Ok(vec![Item::Value(Rc::new(Value::from(
307 n[0].to_double().floor(),
308 )))]),
309 _ => Err(Error::new(
310 ErrorKind::TypeError,
311 String::from("not a singleton sequence"),
312 )),
313 }
314}
315
316pub fn ceiling<
318 N: Node,
319 F: FnMut(&str) -> Result<(), Error>,
320 G: FnMut(&str) -> Result<N, Error>,
321 H: FnMut(&Url) -> Result<String, Error>,
322>(
323 ctxt: &Context<N>,
324 stctxt: &mut StaticContext<N, F, G, H>,
325 c: &Transform<N>,
326) -> Result<Sequence<N>, Error> {
327 let n = ctxt.dispatch(stctxt, c)?;
328 match n.len() {
329 1 => Ok(vec![Item::Value(Rc::new(Value::from(
330 n[0].to_double().ceil(),
331 )))]),
332 _ => Err(Error::new(
333 ErrorKind::TypeError,
334 String::from("not a singleton sequence"),
335 )),
336 }
337}
338
339pub fn round<
341 N: Node,
342 F: FnMut(&str) -> Result<(), Error>,
343 G: FnMut(&str) -> Result<N, Error>,
344 H: FnMut(&Url) -> Result<String, Error>,
345>(
346 ctxt: &Context<N>,
347 stctxt: &mut StaticContext<N, F, G, H>,
348 r: &Transform<N>,
349 pr: &Option<Box<Transform<N>>>,
350) -> Result<Sequence<N>, Error> {
351 match pr {
352 Some(p) => {
353 let n = ctxt.dispatch(stctxt, r)?;
354 let m = ctxt.dispatch(stctxt, p)?;
355 match (n.len(), m.len()) {
356 (1, 1) => Ok(vec![Item::Value(Rc::new(Value::from(
357 ((n[0].to_double() * (10.0_f64).powi(m[0].to_int().unwrap() as i32)).round())
358 * (10.0_f64).powi(-m[0].to_int().unwrap() as i32),
359 )))]),
360 _ => Err(Error::new(
361 ErrorKind::TypeError,
362 String::from("not a singleton sequence"),
363 )),
364 }
365 }
366 None => {
367 let n = ctxt.dispatch(stctxt, r)?;
369 match n.len() {
370 1 => Ok(vec![Item::Value(Rc::new(Value::from(
371 n[0].to_double().round(),
372 )))]),
373 _ => Err(Error::new(
374 ErrorKind::TypeError,
375 String::from("not a singleton sequence"),
376 )),
377 }
378 }
379 }
380}
381
382pub(crate) fn tr_range<
384 N: Node,
385 F: FnMut(&str) -> Result<(), Error>,
386 G: FnMut(&str) -> Result<N, Error>,
387 H: FnMut(&Url) -> Result<String, Error>,
388>(
389 ctxt: &Context<N>,
390 stctxt: &mut StaticContext<N, F, G, H>,
391 start: &Transform<N>,
392 end: &Transform<N>,
393) -> Result<Sequence<N>, Error> {
394 let s = ctxt.dispatch(stctxt, start)?;
395 let e = ctxt.dispatch(stctxt, end)?;
396 if s.is_empty() || e.is_empty() {
397 return Ok(vec![]);
399 }
400 if s.len() != 1 || e.len() != 1 {
401 return Err(Error::new(
402 ErrorKind::TypeError,
403 String::from("operands must be singleton sequence"),
404 ));
405 }
406 let i = s[0].to_int()?;
407 let j = e[0].to_int()?;
408 match i.cmp(&j) {
409 Ordering::Greater => Ok(vec![]),
410 Ordering::Less => {
411 let mut result = Sequence::new();
412 for k in i..=j {
413 result.push_value(&Rc::new(Value::from(k)))
414 }
415 Ok(result)
416 }
417 Ordering::Equal => {
418 let mut seq = Sequence::new();
419 seq.push_value(&Rc::new(Value::from(i)));
420 Ok(seq)
421 }
422 }
423}
424
425pub(crate) fn arithmetic<
427 N: Node,
428 F: FnMut(&str) -> Result<(), Error>,
429 G: FnMut(&str) -> Result<N, Error>,
430 H: FnMut(&Url) -> Result<String, Error>,
431>(
432 ctxt: &Context<N>,
433 stctxt: &mut StaticContext<N, F, G, H>,
434 ops: &Vec<ArithmeticOperand<N>>,
435) -> Result<Sequence<N>, Error> {
436 let mut acc = 0.0;
441 for o in ops {
442 let j = match ctxt.dispatch(stctxt, &o.operand) {
443 Ok(s) => s,
444 Err(_) => {
445 acc = f64::NAN;
446 break;
447 }
448 };
449 if j.len() != 1 {
450 acc = f64::NAN;
451 break;
452 }
453 let u = j[0].to_double();
454 match o.op {
455 ArithmeticOperator::Noop => acc = u,
456 ArithmeticOperator::Add => acc += u,
457 ArithmeticOperator::Subtract => acc -= u,
458 ArithmeticOperator::Multiply => acc *= u,
459 ArithmeticOperator::Divide => acc /= u,
460 ArithmeticOperator::IntegerDivide => acc /= u, ArithmeticOperator::Modulo => acc %= u,
462 }
463 }
464 Ok(vec![Item::Value(Rc::new(Value::from(acc)))])
465}
466
467pub fn format_number<
469 N: Node,
470 F: FnMut(&str) -> Result<(), Error>,
471 G: FnMut(&str) -> Result<N, Error>,
472 H: FnMut(&Url) -> Result<String, Error>,
473>(
474 ctxt: &Context<N>,
475 stctxt: &mut StaticContext<N, F, G, H>,
476 num: &Transform<N>,
477 picture: &Transform<N>,
478 _name: &Option<Box<Transform<N>>>,
479) -> Result<Sequence<N>, Error> {
480 let p = ctxt.dispatch(stctxt, picture)?.to_string();
481 let n = ctxt.dispatch(stctxt, num)?;
482 match n.len() {
483 1 => {
484 match n[0].to_int() {
486 Ok(i) => Ok(vec![Item::Value(Rc::new(Value::from(
487 i.formato(p.as_str()),
488 )))]),
489 _ => {
490 Ok(vec![Item::Value(Rc::new(Value::from(
493 n[0].to_double().formato(p.as_str()),
494 )))])
495 }
496 }
497 }
498 _ => Err(Error::new(
499 ErrorKind::TypeError,
500 String::from("not a singleton sequence"),
501 )),
502 }
503}
504
505pub fn format_integer<
507 N: Node,
508 F: FnMut(&str) -> Result<(), Error>,
509 G: FnMut(&str) -> Result<N, Error>,
510 H: FnMut(&Url) -> Result<String, Error>,
511>(
512 ctxt: &Context<N>,
513 stctxt: &mut StaticContext<N, F, G, H>,
514 num: &Transform<N>,
515 picture: &Transform<N>,
516) -> Result<Sequence<N>, Error> {
517 let p = ctxt.dispatch(stctxt, picture)?.to_string();
518 let numbers = ctxt.dispatch(stctxt, num)?;
519 let mut nit = numbers.iter();
520
521 let mut result = String::new();
522
523 let mut pit = p.chars().peekable();
526 loop {
527 let c = pit.next();
528 if let Some(d) = c {
529 if d.is_alphanumeric() {
530 match d {
531 '0' => {
532 let mut token = String::from(d);
536
537 while let Some(p) = pit.peek() {
538 if p.eq(&'0') {
539 pit.next();
540 token.push('0');
541 } else if p.eq(&'1') {
542 pit.next();
543 token.push('1');
544 } else {
545 break;
546 }
547 }
548
549 if let Some(num) = nit.next() {
550 result.push_str(
551 format!("{:0>1$}", num.to_int()?.to_string(), token.len()).as_str(),
552 );
553 } else {
554 break;
555 }
556 }
557 '1' => {
558 if let Some(num) = nit.next() {
560 result.push_str(num.to_int()?.to_string().as_str())
561 } else {
562 break;
563 }
564 }
565 'A' => {
566 }
568 'a' => {
569 }
571 'i' => {
572 if let Some(num) = nit.next() {
574 result.push_str(
575 roman_converter(u16::try_from(num.to_int()?).map_err(|e| {
576 Error::new(ErrorKind::ParseError, e.to_string())
577 })?)
578 .map_err(|e| Error::new(ErrorKind::ParseError, e))?
579 .to_lowercase()
580 .as_str(),
581 )
582 } else {
583 break;
584 }
585 }
586 'I' => {
587 if let Some(num) = nit.next() {
589 result.push_str(
590 roman_converter(u16::try_from(num.to_int()?).map_err(|e| {
591 Error::new(ErrorKind::ParseError, e.to_string())
592 })?)
593 .map_err(|e| Error::new(ErrorKind::ParseError, e))?
594 .as_str(),
595 )
596 } else {
597 break;
598 }
599 }
600 'w' => {
601 if let Some(num) = nit.next() {
603 result.push_str(
604 convert(
605 num.to_int()?,
606 Formatting {
607 title_case: false,
608 spaces: true,
609 conjunctions: false,
610 commas: false,
611 dashes: false,
612 },
613 )
614 .to_string()
615 .as_str(),
616 )
617 } else {
618 break;
619 }
620 }
621 'W' => {
622 if let Some('w') = pit.peek() {
624 pit.next();
626 if let Some(num) = nit.next() {
627 result.push_str(
628 convert(
629 num.to_int()?,
630 Formatting {
631 title_case: true,
632 spaces: true,
633 conjunctions: false,
634 commas: false,
635 dashes: false,
636 },
637 )
638 .to_string()
639 .as_str(),
640 )
641 } else {
642 break;
643 }
644 } else {
645 if let Some(num) = nit.next() {
647 result.push_str(
648 convert(
649 num.to_int()?,
650 Formatting {
651 title_case: false,
652 spaces: true,
653 conjunctions: false,
654 commas: false,
655 dashes: false,
656 },
657 )
658 .to_string()
659 .to_uppercase()
660 .as_str(),
661 )
662 } else {
663 break;
664 }
665 }
666 }
667 _ => {}
671 }
672 } else {
673 result.push(d)
674 }
675 } else {
676 break;
677 }
678 }
679
680 Ok(vec![Item::Value(Rc::new(Value::from(result)))])
681}