pub use multigrid::*;
pub use multiproduct::*;
pub use single::*;
use super::GpvEncoder;
use crate::WriteToBuffer;
const SECT0_LEN: usize = 16;
pub trait WriteGrib2Message {
type S1<'a>: WriteGrib2Ident
where
Self: 'a;
type Item<'a>: WriteGrib2MessageIterL1
where
Self: 'a;
type Iter<'a>: Iterator<Item = Self::Item<'a>>
where
Self: 'a;
fn discipline(&self) -> u8;
fn reserved(&self) -> [u8; 2] {
[0xff, 0xff]
}
fn section1(&self) -> &Self::S1<'_>;
fn iter(&self) -> Self::Iter<'_>;
fn num_octets(&self) -> usize {
SECT0_LEN
+ self.section1().section1_len()
+ self.iter().map(|m| m.num_octets()).sum::<usize>()
+ crate::SECT8_ES_SIZE
}
fn write(&self, buf: &mut [u8]) -> Result<usize, &'static str> {
let total_len = self.num_octets();
if buf.len() < total_len {
return Err("destination buffer is too small");
}
let mut pos = 0;
pos += write_section0(
self.discipline(),
self.reserved(),
total_len,
&mut buf[pos..],
)?;
pos += self.section1().write_section1(&mut buf[pos..])?;
for m in self.iter() {
pos += m.write(&mut buf[pos..])?;
}
pos += write_section8(&mut buf[pos..])?;
Ok(pos)
}
}
pub trait WriteGrib2MessageIterL1 {
type S2<'a>: WriteGrib2LocalUse
where
Self: 'a;
type Item<'a>: WriteGrib2MessageIterL2
where
Self: 'a;
type Iter<'a>: Iterator<Item = Self::Item<'a>>
where
Self: 'a;
fn section2(&self) -> Option<&Self::S2<'_>>;
fn iter(&self) -> Self::Iter<'_>;
fn num_octets(&self) -> usize {
self.section2().map_or(0, |m| m.section2_len())
+ self.iter().map(|m| m.num_octets()).sum::<usize>()
}
fn write(&self, buf: &mut [u8]) -> Result<usize, &'static str> {
let mut pos = 0;
if let Some(section2) = self.section2() {
pos += section2.write_section2(&mut buf[pos..])?;
}
for m in self.iter() {
pos += m.write(&mut buf[pos..])?;
}
Ok(pos)
}
}
pub trait WriteGrib2MessageIterL2 {
type S3<'a>: WriteGrib2GridDef
where
Self: 'a;
type Item<'a>: WriteGrib2MessageIterL3
where
Self: 'a;
type Iter<'a>: Iterator<Item = Self::Item<'a>>
where
Self: 'a;
fn section3(&self) -> &Self::S3<'_>;
fn iter(&self) -> Self::Iter<'_>;
fn num_octets(&self) -> usize {
self.section3().section3_len() + self.iter().map(|m| m.num_octets()).sum::<usize>()
}
fn write(&self, buf: &mut [u8]) -> Result<usize, &'static str> {
let mut pos = 0;
pos += self.section3().write_section3(&mut buf[pos..])?;
for m in self.iter() {
pos += m.write(&mut buf[pos..])?;
}
Ok(pos)
}
}
pub trait WriteGrib2MessageIterL3 {
type S4<'a>: WriteGrib2ProductDef
where
Self: 'a;
type SD<'a>: WriteGrib2PointValues
where
Self: 'a;
fn section4(&self) -> &Self::S4<'_>;
fn data_sections(&self) -> &Self::SD<'_>;
fn num_octets(&self) -> usize {
self.section4().section4_len() + self.data_sections().data_sections_len()
}
fn write(&self, buf: &mut [u8]) -> Result<usize, &'static str> {
let mut pos = 0;
pos += self.section4().write_section4(&mut buf[pos..])?;
pos += self.data_sections().write_data_sections(&mut buf[pos..])?;
Ok(pos)
}
}
pub trait WriteGrib2Ident {
fn section1_len(&self) -> usize;
fn write_section1(&self, buf: &mut [u8]) -> Result<usize, &'static str>;
}
pub trait WriteGrib2LocalUse {
fn section2_len(&self) -> usize;
fn write_section2(&self, buf: &mut [u8]) -> Result<usize, &'static str>;
}
pub trait WriteGrib2GridDef {
fn section3_len(&self) -> usize;
fn write_section3(&self, buf: &mut [u8]) -> Result<usize, &'static str>;
}
pub trait WriteGrib2ProductDef {
fn section4_len(&self) -> usize;
fn write_section4(&self, buf: &mut [u8]) -> Result<usize, &'static str>;
}
pub trait WriteGrib2PointValues {
fn data_sections_len(&self) -> usize;
fn write_data_sections(&self, buf: &mut [u8]) -> Result<usize, &'static str>;
}
pub trait WriteGrib2DataSections {
fn section5_len(&self) -> usize;
fn write_section5(&self, buf: &mut [u8]) -> Result<usize, &'static str>;
fn section6_len(&self) -> usize;
fn write_section6(&self, buf: &mut [u8]) -> Result<usize, &'static str>;
fn section7_len(&self) -> usize;
fn write_section7(&self, buf: &mut [u8]) -> Result<usize, &'static str>;
}
fn write_section0(
discipline: u8,
reserved: [u8; 2],
len: usize,
buf: &mut [u8],
) -> Result<usize, &'static str> {
if buf.len() < SECT0_LEN {
return Err("destination buffer is too small");
}
let sect = crate::def::grib2::Section0 {
identifier: [0x47, 0x52, 0x49, 0x42],
reserved,
discipline,
edition_num: 2,
total_len: len as u64,
};
let mut pos = 0;
pos += sect.write_to_buffer(&mut buf[pos..])?;
Ok(pos)
}
fn write_section8(buf: &mut [u8]) -> Result<usize, &'static str> {
const SIGNATURE: [u8; 4] = [0x37, 0x37, 0x37, 0x37];
if buf.len() < SIGNATURE.num_bytes_required() {
return Err("destination buffer is too small");
}
SIGNATURE.write_to_buffer(buf)
}
pub(crate) fn write_section_header(
len: u32,
sect_num: u8,
buf: &mut [u8],
) -> Result<usize, &'static str> {
crate::def::grib2::SectionHeader { len, sect_num }.write_to_buffer(buf)
}
mod impls;
mod multigrid;
mod multiproduct;
mod single;