1use crate::metadata;
2use crate::metadata::SiteMetadata;
3use crate::sys;
4use crate::sys::bindings as ll_bindings;
5use crate::Position;
6use crate::SiteId;
7use crate::SizeType;
8use crate::TskitError;
9use ll_bindings::tsk_id_t;
10
11#[derive(Debug)]
13pub struct SiteTableRow {
14 pub id: SiteId,
15 pub position: Position,
16 pub ancestral_state: Option<Vec<u8>>,
17 pub metadata: Option<Vec<u8>>,
18}
19
20impl PartialEq for SiteTableRow {
21 fn eq(&self, other: &Self) -> bool {
22 self.id == other.id
23 && crate::util::partial_cmp_equal(&self.position, &other.position)
24 && self.ancestral_state == other.ancestral_state
25 && self.metadata == other.metadata
26 }
27}
28
29fn make_site_table_row(table: &SiteTable, pos: tsk_id_t) -> Option<SiteTableRow> {
30 let ancestral_state = table.ancestral_state(pos).map(|s| s.to_vec());
31 Some(SiteTableRow {
32 id: pos.into(),
33 position: table.position(pos)?,
34 ancestral_state,
35 metadata: table.table_.raw_metadata(pos).map(|m| m.to_vec()),
36 })
37}
38
39pub(crate) type SiteTableRefIterator<'a> = crate::table_iterator::TableIterator<&'a SiteTable>;
40pub(crate) type SiteTableIterator = crate::table_iterator::TableIterator<SiteTable>;
41
42impl Iterator for SiteTableRefIterator<'_> {
43 type Item = SiteTableRow;
44
45 fn next(&mut self) -> Option<Self::Item> {
46 let rv = make_site_table_row(self.table, self.pos);
47 self.pos += 1;
48 rv
49 }
50}
51
52impl Iterator for SiteTableIterator {
53 type Item = SiteTableRow;
54
55 fn next(&mut self) -> Option<Self::Item> {
56 let rv = make_site_table_row(&self.table, self.pos);
57 self.pos += 1;
58 rv
59 }
60}
61
62#[derive(Debug)]
63pub struct SiteTableRowView<'a> {
64 table: &'a SiteTable,
65 pub id: SiteId,
66 pub position: Position,
67 pub ancestral_state: Option<&'a [u8]>,
68 pub metadata: Option<&'a [u8]>,
69}
70
71impl<'a> SiteTableRowView<'a> {
72 fn new(table: &'a SiteTable) -> Self {
73 Self {
74 table,
75 id: SiteId::NULL,
76 position: f64::NAN.into(),
77 ancestral_state: None,
78 metadata: None,
79 }
80 }
81}
82
83impl PartialEq for SiteTableRowView<'_> {
84 fn eq(&self, other: &Self) -> bool {
85 self.id == other.id
86 && crate::util::partial_cmp_equal(&self.position, &other.position)
87 && self.ancestral_state == other.ancestral_state
88 && self.metadata == other.metadata
89 }
90}
91
92impl Eq for SiteTableRowView<'_> {}
93
94impl PartialEq<SiteTableRow> for SiteTableRowView<'_> {
95 fn eq(&self, other: &SiteTableRow) -> bool {
96 self.id == other.id
97 && crate::util::partial_cmp_equal(&self.position, &other.position)
98 && optional_container_comparison!(self.ancestral_state, other.ancestral_state)
99 && optional_container_comparison!(self.metadata, other.metadata)
100 }
101}
102
103impl PartialEq<SiteTableRowView<'_>> for SiteTableRow {
104 fn eq(&self, other: &SiteTableRowView) -> bool {
105 self.id == other.id
106 && crate::util::partial_cmp_equal(&self.position, &other.position)
107 && optional_container_comparison!(self.ancestral_state, other.ancestral_state)
108 && optional_container_comparison!(self.metadata, other.metadata)
109 }
110}
111
112impl crate::StreamingIterator for SiteTableRowView<'_> {
113 type Item = Self;
114
115 row_lending_iterator_get!();
116
117 fn advance(&mut self) {
118 self.id = (i32::from(self.id) + 1).into();
119 self.position = self
120 .table
121 .position(self.id)
122 .unwrap_or_else(|| f64::NAN.into());
123 self.ancestral_state = self.table.ancestral_state(self.id);
124 self.metadata = self.table.table_.raw_metadata(self.id);
125 }
126}
127
128#[derive(Debug, Default)]
173#[repr(transparent)]
174pub struct SiteTable {
175 table_: sys::SiteTable,
176}
177
178impl SiteTable {
179 pub(crate) unsafe fn new_from_table(
187 sites: *mut ll_bindings::tsk_site_table_t,
188 ) -> Result<Self, TskitError> {
189 let ptr = std::ptr::NonNull::new(sites).unwrap();
190 let table_ = unsafe { sys::SiteTable::new_borrowed(ptr) };
191 Ok(SiteTable { table_ })
192 }
193
194 pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_site_table_t {
195 self.table_.as_ref()
196 }
197
198 pub fn num_rows(&self) -> SizeType {
200 self.as_ref().num_rows.into()
201 }
202
203 pub fn position<S: Into<SiteId> + Copy>(&self, row: S) -> Option<Position> {
210 self.table_.position(row.into())
211 }
212
213 pub fn ancestral_state<S: Into<SiteId>>(&self, row: S) -> Option<&[u8]> {
220 self.table_.ancestral_state(row.into())
221 }
222
223 pub fn metadata<T: metadata::SiteMetadata>(
240 &self,
241 row: impl Into<SiteId>,
242 ) -> Option<Result<T, TskitError>> {
243 let buffer = self.table_.raw_metadata(row)?;
244 Some(decode_metadata_row!(T, buffer).map_err(TskitError::from))
245 }
246
247 pub fn iter(&self) -> impl Iterator<Item = SiteTableRow> + '_ {
250 crate::table_iterator::make_table_iterator::<&SiteTable>(self)
251 }
252
253 pub fn lending_iter(&'_ self) -> SiteTableRowView<'_> {
254 SiteTableRowView::new(self)
255 }
256
257 pub fn row<S: Into<SiteId> + Copy>(&self, r: S) -> Option<SiteTableRow> {
268 let ri = r.into().into();
269 table_row_access!(ri, self, make_site_table_row)
270 }
271
272 pub fn row_view<S: Into<SiteId> + Copy>(&'_ self, r: S) -> Option<SiteTableRowView<'_>> {
283 let view = SiteTableRowView {
284 table: self,
285 id: r.into(),
286 position: self.position(r)?,
287 ancestral_state: self.ancestral_state(r),
288 metadata: self.table_.raw_metadata(r.into()),
289 };
290 Some(view)
291 }
292
293 build_table_column_slice_getter!(
294 => position, position_slice, Position);
296 build_table_column_slice_getter!(
297 => position, position_slice_raw, f64);
299
300 pub fn position_column(&self) -> impl crate::TableColumn<SiteId, Position> + '_ {
301 crate::table_column::OpaqueTableColumn(self.position_slice())
302 }
303
304 pub fn clear(&mut self) -> Result<i32, TskitError> {
306 handle_tsk_return_value!(self.table_.clear())
307 }
308
309 pub fn add_row<P: Into<Position>>(
310 &mut self,
311 position: P,
312 ancestral_state: Option<&[u8]>,
313 ) -> Result<SiteId, TskitError> {
314 let rv = self
315 .table_
316 .add_row(position.into().into(), ancestral_state)?;
317 handle_tsk_return_value!(rv, rv.into())
318 }
319
320 pub fn add_row_with_metadata<P: Into<Position>, M: SiteMetadata>(
321 &mut self,
322 position: P,
323 ancestral_state: Option<&[u8]>,
324 metadata: &M,
325 ) -> Result<SiteId, TskitError> {
326 let md = crate::metadata::EncodedMetadata::new(metadata)?;
327 let rv = self.table_.add_row_with_metadata(
328 position.into().into(),
329 ancestral_state,
330 md.as_slice(),
331 )?;
332 handle_tsk_return_value!(rv, rv.into())
333 }
334}