use crate::chat::ChatItem; use crate::constants::DC_MSG_ID_DAYMARKER; use crate::contact::ContactId; use crate::location::Location; use crate::message::MsgId; /* * the structure behind dc_array_t */ #[derive(Debug, Clone)] pub enum dc_array_t { MsgIds(Vec), ContactIds(Vec), Chat(Vec), Locations(Vec), Uint(Vec), } impl dc_array_t { pub(crate) fn get_id(&self, index: usize) -> u32 { match self { Self::MsgIds(array) => array[index].to_u32(), Self::ContactIds(array) => array[index].to_u32(), Self::Chat(array) => match array[index] { ChatItem::Message { msg_id } => msg_id.to_u32(), ChatItem::DayMarker { .. } => DC_MSG_ID_DAYMARKER, }, Self::Locations(array) => array[index].location_id, Self::Uint(array) => array[index], } } pub(crate) fn get_timestamp(&self, index: usize) -> Option { match self { Self::MsgIds(_) => None, Self::ContactIds(_) => None, Self::Chat(array) => array.get(index).and_then(|item| match item { ChatItem::Message { .. } => None, ChatItem::DayMarker { timestamp } => Some(*timestamp), }), Self::Locations(array) => array.get(index).map(|location| location.timestamp), Self::Uint(_) => None, } } pub(crate) fn get_marker(&self, index: usize) -> Option<&str> { match self { Self::MsgIds(_) => None, Self::ContactIds(_) => None, Self::Chat(_) => None, Self::Locations(array) => array .get(index) .and_then(|location| location.marker.as_deref()), Self::Uint(_) => None, } } pub(crate) fn get_location(&self, index: usize) -> &Location { if let Self::Locations(array) = self { &array[index] } else { panic!("Not an array of locations") } } /// Returns the number of elements in the array. pub(crate) fn len(&self) -> usize { match self { Self::MsgIds(array) => array.len(), Self::ContactIds(array) => array.len(), Self::Chat(array) => array.len(), Self::Locations(array) => array.len(), Self::Uint(array) => array.len(), } } pub(crate) fn search_id(&self, needle: u32) -> Option { (0..self.len()).find(|i| self.get_id(*i) == needle) } } impl From> for dc_array_t { fn from(array: Vec) -> Self { dc_array_t::Uint(array) } } impl From> for dc_array_t { fn from(array: Vec) -> Self { dc_array_t::MsgIds(array) } } impl From> for dc_array_t { fn from(array: Vec) -> Self { dc_array_t::ContactIds(array) } } impl From> for dc_array_t { fn from(array: Vec) -> Self { dc_array_t::Chat(array) } } impl From> for dc_array_t { fn from(array: Vec) -> Self { dc_array_t::Locations(array) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_dc_array() { let arr: dc_array_t = Vec::::new().into(); assert!(arr.len() == 0); let ids: Vec = (2..1002).collect(); let arr: dc_array_t = ids.into(); assert_eq!(arr.len(), 1000); for i in 0..1000 { assert_eq!(arr.get_id(i), (i + 2) as u32); } assert_eq!(arr.search_id(10), Some(8)); assert_eq!(arr.search_id(1), None); } #[test] #[should_panic] fn test_dc_array_out_of_bounds() { let ids: Vec = (2..1002).collect(); let arr: dc_array_t = ids.into(); arr.get_id(1000); } }