1use crate::bindings as ll_bindings;
2use crate::metadata;
3use crate::sys;
4use crate::tsk_id_t;
5use crate::Position;
6use crate::SiteId;
7use crate::SizeType;
8use crate::TskitError;
9
10#[derive(Debug)]
12pub struct SiteTableRow {
13 pub id: SiteId,
14 pub position: Position,
15 pub ancestral_state: Option<Vec<u8>>,
16 pub metadata: Option<Vec<u8>>,
17}
18
19impl PartialEq for SiteTableRow {
20 fn eq(&self, other: &Self) -> bool {
21 self.id == other.id
22 && crate::util::partial_cmp_equal(&self.position, &other.position)
23 && self.ancestral_state == other.ancestral_state
24 && self.metadata == other.metadata
25 }
26}
27
28fn make_site_table_row(table: &SiteTable, pos: tsk_id_t) -> Option<SiteTableRow> {
29 let ancestral_state = table.ancestral_state(pos).map(|s| s.to_vec());
30 Some(SiteTableRow {
31 id: pos.into(),
32 position: table.position(pos)?,
33 ancestral_state,
34 metadata: table.raw_metadata(pos).map(|m| m.to_vec()),
35 })
36}
37
38pub(crate) type SiteTableRefIterator<'a> = crate::table_iterator::TableIterator<&'a SiteTable>;
39pub(crate) type SiteTableIterator = crate::table_iterator::TableIterator<SiteTable>;
40
41impl<'a> Iterator for SiteTableRefIterator<'a> {
42 type Item = SiteTableRow;
43
44 fn next(&mut self) -> Option<Self::Item> {
45 let rv = make_site_table_row(self.table, self.pos);
46 self.pos += 1;
47 rv
48 }
49}
50
51impl Iterator for SiteTableIterator {
52 type Item = SiteTableRow;
53
54 fn next(&mut self) -> Option<Self::Item> {
55 let rv = make_site_table_row(&self.table, self.pos);
56 self.pos += 1;
57 rv
58 }
59}
60
61#[derive(Debug)]
62pub struct SiteTableRowView<'a> {
63 table: &'a SiteTable,
64 pub id: SiteId,
65 pub position: Position,
66 pub ancestral_state: Option<&'a [u8]>,
67 pub metadata: Option<&'a [u8]>,
68}
69
70impl<'a> SiteTableRowView<'a> {
71 fn new(table: &'a SiteTable) -> Self {
72 Self {
73 table,
74 id: SiteId::NULL,
75 position: f64::NAN.into(),
76 ancestral_state: None,
77 metadata: None,
78 }
79 }
80}
81
82impl<'a> PartialEq for SiteTableRowView<'a> {
83 fn eq(&self, other: &Self) -> bool {
84 self.id == other.id
85 && crate::util::partial_cmp_equal(&self.position, &other.position)
86 && self.ancestral_state == other.ancestral_state
87 && self.metadata == other.metadata
88 }
89}
90
91impl<'a> Eq for SiteTableRowView<'a> {}
92
93impl<'a> PartialEq<SiteTableRow> for SiteTableRowView<'a> {
94 fn eq(&self, other: &SiteTableRow) -> bool {
95 self.id == other.id
96 && crate::util::partial_cmp_equal(&self.position, &other.position)
97 && optional_container_comparison!(self.ancestral_state, other.ancestral_state)
98 && optional_container_comparison!(self.metadata, other.metadata)
99 }
100}
101
102impl PartialEq<SiteTableRowView<'_>> for SiteTableRow {
103 fn eq(&self, other: &SiteTableRowView) -> bool {
104 self.id == other.id
105 && crate::util::partial_cmp_equal(&self.position, &other.position)
106 && optional_container_comparison!(self.ancestral_state, other.ancestral_state)
107 && optional_container_comparison!(self.metadata, other.metadata)
108 }
109}
110
111impl<'a> streaming_iterator::StreamingIterator for SiteTableRowView<'a> {
112 type Item = Self;
113
114 row_lending_iterator_get!();
115
116 fn advance(&mut self) {
117 self.id = (i32::from(self.id) + 1).into();
118 self.position = self
119 .table
120 .position(self.id)
121 .unwrap_or_else(|| f64::NAN.into());
122 self.ancestral_state = self.table.ancestral_state(self.id);
123 self.metadata = self.table.raw_metadata(self.id);
124 }
125}
126
127#[derive(Debug)]
129#[repr(transparent)]
130pub struct SiteTable {
131 table_: sys::LLSiteTableRef,
132}
133
134impl SiteTable {
135 pub(crate) fn new_from_table(
136 sites: *mut ll_bindings::tsk_site_table_t,
137 ) -> Result<Self, TskitError> {
138 let table_ = sys::LLSiteTableRef::new_from_table(sites)?;
139 Ok(SiteTable { table_ })
140 }
141
142 pub(crate) fn as_ref(&self) -> &ll_bindings::tsk_site_table_t {
143 self.table_.as_ref()
144 }
145
146 raw_metadata_getter_for_tables!(SiteId);
147
148 pub fn num_rows(&self) -> SizeType {
150 self.as_ref().num_rows.into()
151 }
152
153 pub fn position<S: Into<SiteId> + Copy>(&self, row: S) -> Option<Position> {
160 sys::tsk_column_access::<Position, _, _, _>(
161 row.into(),
162 self.as_ref().position,
163 self.num_rows(),
164 )
165 }
166
167 pub fn ancestral_state<S: Into<SiteId>>(&self, row: S) -> Option<&[u8]> {
174 sys::tsk_ragged_column_access(
175 row.into(),
176 self.as_ref().ancestral_state,
177 self.num_rows(),
178 self.as_ref().ancestral_state_offset,
179 self.as_ref().ancestral_state_length,
180 )
181 }
182
183 pub fn metadata<T: metadata::SiteMetadata>(
200 &self,
201 row: SiteId,
202 ) -> Option<Result<T, TskitError>> {
203 let buffer = self.raw_metadata(row)?;
204 Some(decode_metadata_row!(T, buffer).map_err(TskitError::from))
205 }
206
207 pub fn iter(&self) -> impl Iterator<Item = SiteTableRow> + '_ {
210 crate::table_iterator::make_table_iterator::<&SiteTable>(self)
211 }
212
213 pub fn lending_iter(&self) -> SiteTableRowView {
214 SiteTableRowView::new(self)
215 }
216
217 pub fn row<S: Into<SiteId> + Copy>(&self, r: S) -> Option<SiteTableRow> {
228 let ri = r.into().into();
229 table_row_access!(ri, self, make_site_table_row)
230 }
231
232 pub fn row_view<S: Into<SiteId> + Copy>(&self, r: S) -> Option<SiteTableRowView> {
243 let view = SiteTableRowView {
244 table: self,
245 id: r.into(),
246 position: self.position(r)?,
247 ancestral_state: self.ancestral_state(r),
248 metadata: self.raw_metadata(r.into()),
249 };
250 Some(view)
251 }
252
253 build_table_column_slice_getter!(
254 => position, position_slice, Position);
256 build_table_column_slice_getter!(
257 => position, position_slice_raw, f64);
259}
260
261build_owned_table_type!(
262 => OwningSiteTable,
307 SiteTable,
308 crate::sys::LLOwningSiteTable,
309 crate::bindings::tsk_site_table_t
310);
311
312impl OwningSiteTable {
313 site_table_add_row!(=> add_row, self, self.as_mut_ptr());
314 site_table_add_row_with_metadata!(=> add_row_with_metadata, self, self.as_mut_ptr());
315}