use std::io;
use protohoggr::{encode_bytes_field, encode_int64_field, encode_sint64_field_always};
pub struct HeaderBuilder<'a> {
bbox: Option<(f64, f64, f64, f64)>,
replication_timestamp: Option<i64>,
replication_sequence_number: Option<i64>,
replication_base_url: Option<&'a str>,
optional_features: Vec<&'a str>,
historical_information: bool,
sorted: bool,
writing_program: &'a str,
}
impl Default for HeaderBuilder<'_> {
fn default() -> Self {
Self::new()
}
}
impl<'a> HeaderBuilder<'a> {
#[must_use]
pub fn new() -> Self {
HeaderBuilder {
bbox: None,
replication_timestamp: None,
replication_sequence_number: None,
replication_base_url: None,
optional_features: Vec::new(),
historical_information: false,
sorted: false,
writing_program: "pbfhogg",
}
}
#[must_use]
pub fn from_header(header: &'a crate::HeaderBlock) -> Self {
let mut hb = Self::new();
if let Some(b) = header.bbox() {
hb.bbox = Some((b.left, b.bottom, b.right, b.top));
}
hb.replication_timestamp = header.osmosis_replication_timestamp();
hb.replication_sequence_number = header.osmosis_replication_sequence_number();
hb.replication_base_url = header.osmosis_replication_base_url();
hb.historical_information = header.has_historical_information();
hb
}
#[must_use]
pub fn bbox(mut self, left: f64, bottom: f64, right: f64, top: f64) -> Self {
self.bbox = Some((left, bottom, right, top));
self
}
#[must_use]
pub fn replication_timestamp(mut self, ts: i64) -> Self {
self.replication_timestamp = Some(ts);
self
}
#[must_use]
pub fn replication_sequence_number(mut self, seq: i64) -> Self {
self.replication_sequence_number = Some(seq);
self
}
#[must_use]
pub fn replication_base_url(mut self, url: &'a str) -> Self {
self.replication_base_url = Some(url);
self
}
#[must_use]
pub fn sorted(mut self) -> Self {
self.sorted = true;
self
}
#[must_use]
pub fn optional_feature(mut self, feature: &'a str) -> Self {
self.optional_features.push(feature);
self
}
#[must_use]
pub fn historical(mut self) -> Self {
self.historical_information = true;
self
}
#[must_use]
pub fn writing_program(mut self, program: &'a str) -> Self {
self.writing_program = program;
self
}
#[allow(clippy::cast_possible_truncation)]
pub fn build(self) -> io::Result<Vec<u8>> {
let mut buf = Vec::new();
if let Some((left, bottom, right, top)) = self.bbox {
let mut bbox_buf = Vec::new();
encode_sint64_field_always(&mut bbox_buf, 1, (left * 1e9).round() as i64);
encode_sint64_field_always(&mut bbox_buf, 2, (right * 1e9).round() as i64);
encode_sint64_field_always(&mut bbox_buf, 3, (top * 1e9).round() as i64);
encode_sint64_field_always(&mut bbox_buf, 4, (bottom * 1e9).round() as i64);
encode_bytes_field(&mut buf, 1, &bbox_buf);
}
encode_bytes_field(&mut buf, 4, b"OsmSchema-V0.6");
encode_bytes_field(&mut buf, 4, b"DenseNodes");
if self.historical_information {
encode_bytes_field(&mut buf, 4, crate::HeaderBlock::HISTORICAL_INFORMATION.as_bytes());
}
if self.sorted {
encode_bytes_field(&mut buf, 5, crate::HeaderBlock::SORT_TYPE_THEN_ID.as_bytes());
}
for feature in &self.optional_features {
encode_bytes_field(&mut buf, 5, feature.as_bytes());
}
encode_bytes_field(&mut buf, 16, self.writing_program.as_bytes());
if let Some(ts) = self.replication_timestamp {
encode_int64_field(&mut buf, 32, ts);
}
if let Some(seq) = self.replication_sequence_number {
encode_int64_field(&mut buf, 33, seq);
}
if let Some(url) = self.replication_base_url {
encode_bytes_field(&mut buf, 34, url.as_bytes());
}
Ok(buf)
}
}