1use crate::{
2 context::BlobData,
3 error::Error,
4 prelude::{ProductType, QcContext, SP3},
5};
6
7use qc_traits::Merge;
8
9use std::path::Path;
10
11impl QcContext {
12 pub fn load_sp3<P: AsRef<Path>>(&mut self, path: P, sp3: SP3) -> Result<(), Error> {
16 let prod_type = ProductType::HighPrecisionOrbit;
17
18 let path_buf = path.as_ref().to_path_buf();
19
20 if let Some(paths) = self
22 .files
23 .iter_mut()
24 .filter_map(|(prod, files)| {
25 if *prod == prod_type {
26 Some(files)
27 } else {
28 None
29 }
30 })
31 .reduce(|k, _| k)
32 {
33 if let Some(inner) = self.blob.get_mut(&prod_type).and_then(|k| k.as_mut_sp3()) {
34 inner.merge_mut(&sp3)?;
35 paths.push(path_buf);
36 }
37 } else {
38 self.blob.insert(prod_type, BlobData::SP3(sp3));
39 self.files.insert(prod_type, vec![path_buf]);
40 }
41 Ok(())
42 }
43
44 pub fn load_sp3_file<P: AsRef<Path>>(&mut self, path: P) -> Result<(), Error> {
46 let sp3 = SP3::from_file(&path)?;
47 self.load_sp3(path, sp3)
48 }
49
50 pub fn has_sp3(&self) -> bool {
52 self.sp3().is_some()
53 }
54
55 pub fn sp3_has_clock(&self) -> bool {
57 if let Some(sp3) = self.sp3() {
58 sp3.has_satellite_clock_offset()
59 } else {
60 false
61 }
62 }
63
64 pub fn sp3(&self) -> Option<&SP3> {
66 self.data(ProductType::HighPrecisionOrbit)?.as_sp3()
67 }
68
69 pub fn sp3_mut(&mut self) -> Option<&mut SP3> {
71 self.data_mut(ProductType::HighPrecisionOrbit)?.as_mut_sp3()
72 }
73
74 pub fn is_ppp_ultra_navigation_compatible(&self) -> bool {
75 self.clock().is_some() && self.sp3_has_clock() && self.is_cpp_navigation_compatible()
79 }
80}