spreadsheet_mcp/diff/
cells.rs1use super::address::CellAddress;
2use super::sst::Sst;
3use anyhow::{Result, anyhow};
4use quick_xml::events::{BytesStart, Event};
5use quick_xml::reader::Reader;
6use std::io::BufRead;
7
8#[derive(Debug)]
9pub struct RawCell {
10 pub address: CellAddress,
11 pub value: Option<String>,
12 pub formula: Option<String>,
13 pub style_id: Option<u32>,
14}
15
16pub struct CellIterator<'a, R: BufRead> {
17 reader: Reader<R>,
18 sst: Option<&'a Sst>,
19 buf: Vec<u8>,
20}
21
22impl<'a, R: BufRead> CellIterator<'a, R> {
23 pub fn new(reader: R, sst: Option<&'a Sst>) -> Self {
24 let reader = Reader::from_reader(reader);
25 Self {
26 reader,
27 sst,
28 buf: Vec::new(),
29 }
30 }
31
32 fn read_text_content(&mut self, end_tag: &[u8]) -> Result<String> {
33 let mut text = String::new();
34 let mut buf = Vec::new();
35 loop {
36 match self.reader.read_event_into(&mut buf)? {
37 Event::Text(e) => text.push_str(&e.unescape()?),
38 Event::CData(e) => text.push_str(&String::from_utf8_lossy(&e)),
39 Event::End(e) if e.name().as_ref() == end_tag => break,
40 Event::Eof => return Err(anyhow!("Unexpected EOF reading text")),
41 _ => (),
42 }
43 buf.clear();
44 }
45 Ok(text)
46 }
47
48 fn parse_cell(&mut self, e: &BytesStart) -> Result<RawCell> {
49 let mut address_str = String::new();
50 let mut type_str = String::new();
51 let mut style_id: Option<u32> = None;
52
53 for attr in e.attributes() {
54 let attr = attr?;
55 if attr.key.as_ref() == b"r" {
56 address_str = String::from_utf8_lossy(&attr.value).to_string();
57 } else if attr.key.as_ref() == b"t" {
58 type_str = String::from_utf8_lossy(&attr.value).to_string();
59 } else if attr.key.as_ref() == b"s" {
60 let s = String::from_utf8_lossy(&attr.value).to_string();
61 style_id = s.parse::<u32>().ok();
62 }
63 }
64
65 if address_str.is_empty() {
66 return Err(anyhow!("Cell missing address"));
67 }
68 let address = CellAddress::parse(&address_str)
69 .ok_or_else(|| anyhow!("Invalid cell address: {}", address_str))?;
70
71 let mut value = None;
72 let mut formula = None;
73 let mut buf = Vec::new();
74
75 loop {
76 match self.reader.read_event_into(&mut buf) {
77 Ok(Event::Start(ref e)) => {
78 match e.name().as_ref() {
79 b"v" => {
80 let text = self.read_text_content(b"v")?;
81 value = Some(text);
82 }
83 b"f" => {
84 let text = self.read_text_content(b"f")?;
85 formula = Some(text);
86 }
87 b"is" => {
88 }
91 _ => {}
92 }
93 }
94 Ok(Event::End(ref e)) if e.name().as_ref() == b"c" => {
95 break;
96 }
97 Ok(Event::Eof) => break,
98 Err(e) => return Err(e.into()),
99 _ => {}
100 }
101 buf.clear();
102 }
103
104 if type_str == "s"
106 && let Some(ref v) = value
107 && let Ok(idx) = v.parse::<usize>()
108 && let Some(sst) = self.sst
109 && let Some(s) = sst.get(idx)
110 {
111 value = Some(s.to_string());
112 }
113
114 Ok(RawCell {
115 address,
116 value,
117 formula,
118 style_id,
119 })
120 }
121}
122
123impl<'a, R: BufRead> Iterator for CellIterator<'a, R> {
124 type Item = Result<RawCell>;
125
126 fn next(&mut self) -> Option<Self::Item> {
127 loop {
128 self.buf.clear();
129 match self.reader.read_event_into(&mut self.buf) {
130 Ok(Event::Start(ref e)) if e.name().as_ref() == b"c" => {
131 let e_owned = e.to_owned();
133 return Some(self.parse_cell(&e_owned));
134 }
135 Ok(Event::Eof) => return None,
136 Err(e) => return Some(Err(e.into())),
137 _ => {}
138 }
139 }
140 }
141}