wkb_raster/
lib.rs

1//! [Well Known Binary format for PostGIS RASTER type](https://github.com/postgis/postgis/blob/master/raster/doc/RFC2-WellKnownBinaryFormat)
2//! 
3//! The WKB format for RASTER is meant for transport and
4//! takes into account endianness and avoids any padding.
5//! Still, beside padding and endianness, it matches the
6//! internal serialized format (see RFC1), for quick
7//! input/output.
8//!
9//! # Example
10//!
11//! ## Raster to WKB string
12//! 
13//! ```rust
14//! use wkb_raster::{Raster, RasterBand, RasterDataSource, InMemoryRasterData, Endian};
15//! 
16//! // 2x2 image bytes, u8 format
17//! let bytes = vec![
18//!     vec![0, 1], 
19//!     vec![1, 0],
20//! ];
21//!
22//! let raster = Raster {
23//!     endian: Endian::Big,    // note: currently Endian::Little is not supported in PostGIS
24//!     version: 0,             // always set to 0
25//!     scale_x: 1.0,           // pixel width in degrees
26//!     scale_y: 1.0,           // pixel height in degrees
27//!     ip_x: 0.0,              // upper left corner longitude in degrees
28//!     ip_y: 0.0,              // upper left corner latitude in degrees
29//!     skew_x: 0.0,            // rotation in degrees (0 to 360)
30//!     skew_y: 0.0,            // rotation in degrees (0 to 360)
31//!     srid: 4326,             // SRID EPSG identifier
32//!     width: 2,               // pixel columns
33//!     height: 2,              // rows
34//!     bands: vec![RasterBand {
35//!         is_nodata_value: false           // true only if entire band is NODATA
36//!         data: RasterDataSource::InMemory(
37//!             InMemoryRasterData::UInt8 {
38//!                 data: bytes,
39//!                 nodata
40//!             }
41//!         ),
42//!     }],
43//! };
44//! 
45//! assert_eq!(
46//!     raster.to_wkb_string(), 
47//!     String::from("00000000013FF00000000000003FF00000000000000000000000000000000000000000000000000000000000000000000000000000000010E600020002040000010100")
48//! );
49//! ```
50//!
51//! ## WKB string to raster
52//! 
53//! ```rust
54//! use wkb_raster::{Raster, RasterBand, RasterDataSource, InMemoryRasterData, Endian};
55//!
56//! let parsed_raster = Raster::from_wkb_string(b"00000000013FF00000000000003FF00000000000000000000000000000000000000000000000000000000000000000000000000000000010E600020002040000010100").unwrap();
57//! 
58//! // 2x2 image bytes, u8 format
59//! let bytes = vec![
60//!     vec![0, 1], 
61//!     vec![1, 0],
62//! ];
63//! 
64//! assert_eq!(parsed_raster, Raster {
65//!     endian: Endian::Big,
66//!     version: 0,
67//!     scale_x: 1.0,
68//!     scale_y: 1.0,
69//!     ip_x: 0.0,
70//!     ip_y: 0.0,
71//!     skew_x: 0.0,
72//!     skew_y: 0.0,
73//!     srid: 4326,
74//!     width: 2,
75//!     height: 2,
76//!     bands: vec![RasterBand {
77//!         is_nodata_value: false,
78//!         data: RasterDataSource::InMemory(
79//!             InMemoryRasterData::UInt8 {
80//!                 data: bytes,
81//!                 nodata
82//!             }
83//!         ),
84//!     }],
85//! });
86//! ```
87
88// ```ignore
89// // Basic Type definitions
90// // byte : 1 byte
91// // uint16 : 16 bit unsigned integer (2 bytes)
92// // uint32 : 32 bit unsigned integer (4 bytes)
93// // float64 : double precision floating point number (8 bytes)
94// 
95//  +------------------------------------------------------------+
96//  | RASTER                                                     |
97//  +---------------+-------------+------------------------------+
98//  | - name -      |  - type -   | - meaning -                  |
99//  +---------------+-------------+------------------------------+
100//  | endiannes     | byte        | 1:ndr/little endian          |
101//  |               |             | 0:xdr/big endian             |
102//  +---------------+-------------+------------------------------+
103//  | version       | uint16      | format version (0 for this   |
104//  |               |             | structure)                   |
105//  +---------------+-------------+------------------------------+
106//  | nBands        | uint16      | Number of bands              |
107//  +---------------+-------------+------------------------------+
108//  | scaleX        | float64     | pixel width                  |
109//  |               |             | in geographical units        |
110//  +---------------+-------------+------------------------------+
111//  | scaleY        | float64     | pixel height                 |
112//  |               |             | in geographical units        |
113//  +---------------+-------------+------------------------------+
114//  | ipX           | float64     | X ordinate of upper-left     |
115//  |               |             | pixel's upper-left corner    |
116//  |               |             | in geographical units        |
117//  +---------------+-------------+------------------------------+
118//  | ipY           | float64     | Y ordinate of upper-left     |
119//  |               |             | pixel's upper-left corner    |
120//  |               |             | in geographical units        |
121//  +---------------+-------------+------------------------------+
122//  | skewX         | float64     | rotation about Y-axis        |
123//  +---------------+-------------+------------------------------+
124//  | skewY         | float64     | rotation about X-axis        |
125//  +---------------+-------------+------------------------------+
126//  | srid          | int32       | Spatial reference id         |
127//  +---------------+-------------+------------------------------+
128//  | width         | uint16      | number of pixel columns      |
129//  +---------------+-------------+------------------------------+
130//  | height        | uint16      | number of pixel rows         |
131//  +---------------+-------------+------------------------------+
132//  | bands[nBands] | RASTERBAND  | Bands data                   |
133//  +---------------+-------------+------------------------------+
134// 
135// 
136//  +------------------------------------------------------------------+
137//  | RASTERBAND                                                       |
138//  +---------------+--------------+-----------------------------------+
139//  | - name -      |  - type -    | - meaning -                       |
140//  +---------------+--------------+-----------------------------------+
141//  | isOffline     | 1bit         | If true, data is to be found      |
142//  |               |              | on the filesystem, trought the    |
143//  |               |              | path specified in RASTERDATA      |
144//  +---------------+--------------+-----------------------------------+
145//  | hasNodataValue| 1bit         | If true, stored nodata value is   |
146//  |               |              | a true nodata value. Otherwise    |
147//  |               |              | the value stored as a nodata      |
148//  |               |              | value should be ignored.          | 
149//  +---------------+--------------+-----------------------------------+
150//  | isNodataValue | 1bit         | If true, all the values of the    |
151//  |               |              | band are expected to be nodata    |
152//  |               |              | values. This is a dirty flag.     |
153//  |               |              | To set the flag to its real value |
154//  |               |              | the function st_bandisnodata must |
155//  |               |              | must be called for the band with  | 
156//  |               |              | 'TRUE' as last argument.          |
157//  +---------------+--------------+-----------------------------------+
158//  | reserved      | 1bit         | unused in this version            |
159//  +---------------+--------------+-----------------------------------+
160//  | pixtype       | 4bits        | 0: 1-bit boolean                  |
161//  |               |              | 1: 2-bit unsigned integer         |
162//  |               |              | 2: 4-bit unsigned integer         |
163//  |               |              | 3: 8-bit signed integer           |
164//  |               |              | 4: 8-bit unsigned integer         |
165//  |               |              | 5: 16-bit signed integer          |
166//  |               |              | 6: 16-bit unsigned signed integer |
167//  |               |              | 7: 32-bit signed integer          |
168//  |               |              | 8: 32-bit unsigned signed integer |
169//  |               |              | 10: 32-bit float                  |
170//  |               |              | 11: 64-bit float                  |
171//  +---------------+--------------+-----------------------------------+
172//  | nodata        | 1 to 8 bytes | Nodata value                      |
173//  |               | depending on |                                   |
174//  |               | pixtype [1]  |                                   |
175//  +---------------+--------------+-----------------------------------+
176//  | data          | RASTERDATA   | Raster band data (see below)      |
177//  +---------------+--------------+-----------------------------------+
178// 
179//  +------------------------------------------------------------------+
180//  | RASTERDATA (isOffline flag clear)                                |
181//  +---------------+--------------+-----------------------------------+
182//  | pix[w*h]      | 1 to 8 bytes | Pixels values, row after row,     |
183//  |               | depending on | so pix[0] is upper-left, pix[w-1] |
184//  |               | pixtype [1]  | is upper-right.                   |
185//  |               |              |                                   |
186//  |               |              | As for endiannes, it is specified |
187//  |               |              | at the start of WKB, and implicit |
188//  |               |              | up to 8bits (bit-order is most    |
189//  |               |              | significant first)                |
190//  |               |              |                                   |
191//  +---------------+--------------+-----------------------------------+
192// 
193//  [1] 1,2 and 4 bit pixtypes are still encoded as 1-byte per value
194// 
195//  +-----------------------------------------------------------------+
196//  | RASTERDATA (isOffline flag set)                                 |
197//  +---------------+-------------+-----------------------------------+
198//  | bandNumber    | int8        | 0-based band number to use from   |
199//  |               |             | the set available in the external |
200//  |               |             | file                              |
201//  +---------------+-------------+-----------------------------------+
202//  | path          | string      | null-terminated path to data file |
203//  +---------------+-------------+-----------------------------------+
204// ```
205
206use std::path::PathBuf;
207use std::ffi::CString;
208
209#[macro_use]
210mod parse_memory_data;
211mod big_endian;
212mod little_endian;
213
214#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
215pub enum ParseError {
216    WrongInputSize { expected_len: usize, got: Vec<u8> },
217    UnableToParseBool(BoolParseError),
218    NoEndiannessGiven([u8;2]),
219    InvalidPixelType(u8),
220    FromBytesWithNulError(Vec<u8>),
221    PathContainsNonUTF8Chars(CString),
222}
223
224#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Hash, Eq, Ord)]
225pub struct BoolParseError([u8;2], u8);
226
227impl From<BoolParseError> for ParseError {
228    fn from(e: BoolParseError) -> Self {
229        ParseError::UnableToParseBool(e)
230    }
231}
232
233/// Raster data 
234#[derive(Debug, Clone, PartialEq, PartialOrd)]
235pub struct Raster {
236    /// Endinanness, 1:ndr/little endian, 0:xdr/big endian
237    pub endian: Endian,
238    /// format version (0 for this structure)                 
239    pub version: u16,
240    /// pixel width in geographical units  
241    pub scale_x: f64,
242    /// pixel height in geographical units  
243    pub scale_y: f64,
244    /// X ordinate of upper-left pixel's upper-left corner in geographical units        
245    pub ip_x: f64,
246    /// Y ordinate of upper-left pixel's upper-left corner in geographical units        
247    pub ip_y: f64,
248    /// rotation about Y-axis
249    pub skew_x: f64,
250    /// rotation about X-axis
251    pub skew_y: f64,
252    /// Spatial reference id
253    pub srid: i32,
254    /// Number of pixel columns
255    pub width: u16,
256    /// Number of pixel rows
257    pub height: u16,
258    /// Bands data
259    pub bands: Vec<RasterBand>,
260}
261
262#[inline]
263fn take_slice_1_byte(input: &[u8]) -> Result<([u8;2], &[u8]), ParseError> {
264    use self::ParseError::*;
265    const MIN_LEN: usize = 2;
266    if input.len() < MIN_LEN { 
267        return Err(WrongInputSize { expected_len: MIN_LEN, got: input.to_vec() });
268    }
269    unsafe {
270        let a = input.get_unchecked(0);
271        let b = input.get_unchecked(1);
272        Ok(([*a, *b], &input[MIN_LEN..]))
273    }
274}
275
276#[inline]
277fn take_slice_2_bytes(input: &[u8]) -> Result<([u8;4], &[u8]), ParseError> {
278    use self::ParseError::*;
279    const MIN_LEN: usize = 4;
280    if input.len() < MIN_LEN { 
281        return Err(WrongInputSize { expected_len: MIN_LEN, got: input.to_vec() });
282    }
283    unsafe {
284        let a = input.get_unchecked(0);
285        let b = input.get_unchecked(1);
286        let c = input.get_unchecked(2);
287        let d = input.get_unchecked(3);
288        Ok(([*a, *b, *c, *d], &input[MIN_LEN..]))
289    }
290}
291
292#[inline]
293fn take_slice_4_bytes(input: &[u8]) -> Result<([u8;8], &[u8]), ParseError> {
294    use self::ParseError::*;
295    const MIN_LEN: usize = 8;
296    if input.len() < MIN_LEN { 
297        return Err(WrongInputSize { expected_len: MIN_LEN, got: input.to_vec() });
298    }
299    unsafe {
300        let a = input.get_unchecked(0);
301        let b = input.get_unchecked(1);
302        let c = input.get_unchecked(2);
303        let d = input.get_unchecked(3);
304        let e = input.get_unchecked(4);
305        let f = input.get_unchecked(5);
306        let g = input.get_unchecked(6);
307        let h = input.get_unchecked(7);
308        Ok(([*a, *b, *c, *d, *e, *f, *g, *h], &input[MIN_LEN..]))
309    }
310}
311
312#[inline]
313fn take_slice_8_bytes(input: &[u8]) -> Result<([u8;16], &[u8]), ParseError> {
314    use self::ParseError::*;
315    const MIN_LEN: usize = 16;
316    if input.len() < MIN_LEN { 
317        return Err(WrongInputSize { expected_len: MIN_LEN, got: input.to_vec() });
318    }
319    unsafe {
320        let a = input.get_unchecked(0);
321        let b = input.get_unchecked(1);
322        let c = input.get_unchecked(2);
323        let d = input.get_unchecked(3);
324        let e = input.get_unchecked(4);
325        let f = input.get_unchecked(5);
326        let g = input.get_unchecked(6);
327        let h = input.get_unchecked(7);
328
329        let i = input.get_unchecked(8);
330        let j = input.get_unchecked(9);
331        let k = input.get_unchecked(10);
332        let l = input.get_unchecked(11);
333        let m = input.get_unchecked(12);
334        let n = input.get_unchecked(13);
335        let o = input.get_unchecked(14);
336        let p = input.get_unchecked(15);
337
338        Ok((
339            [*a, *b, *c, *d, *e, *f, *g, *h,
340             *i, *j, *k, *l, *m, *n, *o, *p], 
341        &input[MIN_LEN..]
342        ))
343    }
344}
345
346impl Raster {
347
348    /// Outputs the raster as a Well-Known-Binary string, ready to be used in SQL statements
349    pub fn to_wkb_string(self) -> String {
350        match self.endian {
351            Endian::Big => self.to_wkb_string_big_endian(),
352            Endian::Little => self.to_wkb_string_little_endian(),
353        }
354    }
355
356    pub fn from_wkb_string(string_bytes: &[u8]) -> Result<Self, ParseError> {
357        use self::ParseError::*;
358        match take_slice_1_byte(string_bytes)? {
359            ([b'0', b'0'], input) => Self::from_wkb_string_big_endian(input),
360            ([b'0', b'1'], input) => Self::from_wkb_string_little_endian(input),
361            (other, _) => Err(NoEndiannessGiven(other)),
362        }
363    }
364
365    fn from_wkb_string_big_endian(input: &[u8]) -> Result<Self, ParseError> {
366
367        use crate::big_endian::*;
368        
369        let (version_bytes, input) = take_slice_2_bytes(input)?;
370        let version = parse_u16_be(version_bytes);
371
372        let (nbands_bytes, input) = take_slice_2_bytes(input)?;
373        let nbands = parse_u16_be(nbands_bytes);
374
375        let (scale_x_bytes, input) = take_slice_8_bytes(input)?;
376        let scale_x = parse_f64_be(scale_x_bytes);
377
378        let (scale_y_bytes, input) = take_slice_8_bytes(input)?;
379        let scale_y = parse_f64_be(scale_y_bytes);
380
381        let (ip_x_bytes, input) = take_slice_8_bytes(input)?;
382        let ip_x = parse_f64_be(ip_x_bytes);
383
384        let (ip_y_bytes, input) = take_slice_8_bytes(input)?;
385        let ip_y = parse_f64_be(ip_y_bytes);
386
387        let (skew_x_bytes, input) = take_slice_8_bytes(input)?;
388        let skew_x = parse_f64_be(skew_x_bytes);
389
390        let (skew_y_bytes, input) = take_slice_8_bytes(input)?;
391        let skew_y = parse_f64_be(skew_y_bytes);
392
393        let (srid_bytes, input) = take_slice_4_bytes(input)?;
394        let srid = parse_i32_be(srid_bytes);
395        
396        let (width_bytes, input) = take_slice_2_bytes(input)?;
397        let width = parse_u16_be(width_bytes);
398
399        let (height_bytes, mut input) = take_slice_2_bytes(input)?;
400        let height = parse_u16_be(height_bytes);
401
402        let mut raster_bands = Vec::with_capacity(nbands as usize);
403
404        for _ in 0..(nbands as usize) {
405            let (raster_band, rt_input) = RasterBand::from_wkb_string_big_endian(input, width, height)?;
406            input = rt_input;
407            raster_bands.push(raster_band);
408        }
409
410        Ok(Raster {
411            endian: Endian::Big,
412            version,
413            scale_x,
414            scale_y,
415            ip_x,
416            ip_y,
417            skew_x,
418            skew_y,
419            srid,
420            width,
421            height,
422            bands: raster_bands,
423        })
424    }
425
426    fn from_wkb_string_little_endian(input: &[u8]) -> Result<Self, ParseError> {
427        use crate::little_endian::*;
428        
429        let (version_bytes, input) = take_slice_2_bytes(input)?;
430        let version = parse_u16_le(version_bytes);
431
432        let (nbands_bytes, input) = take_slice_2_bytes(input)?;
433        let nbands = parse_u16_le(nbands_bytes);
434
435        let (scale_x_bytes, input) = take_slice_8_bytes(input)?;
436        let scale_x = parse_f64_le(scale_x_bytes);
437
438        let (scale_y_bytes, input) = take_slice_8_bytes(input)?;
439        let scale_y = parse_f64_le(scale_y_bytes);
440
441        let (ip_x_bytes, input) = take_slice_8_bytes(input)?;
442        let ip_x = parse_f64_le(ip_x_bytes);
443
444        let (ip_y_bytes, input) = take_slice_8_bytes(input)?;
445        let ip_y = parse_f64_le(ip_y_bytes);
446
447        let (skew_x_bytes, input) = take_slice_8_bytes(input)?;
448        let skew_x = parse_f64_le(skew_x_bytes);
449
450        let (skew_y_bytes, input) = take_slice_8_bytes(input)?;
451        let skew_y = parse_f64_le(skew_y_bytes);
452
453        let (srid_bytes, input) = take_slice_4_bytes(input)?;
454        let srid = parse_i32_le(srid_bytes);
455        
456        let (width_bytes, input) = take_slice_2_bytes(input)?;
457        let width = parse_u16_le(width_bytes);
458
459        let (height_bytes, mut input) = take_slice_2_bytes(input)?;
460        let height = parse_u16_le(height_bytes);
461
462        let mut raster_bands = Vec::with_capacity(nbands as usize);
463
464        for _ in 0..(nbands as usize) {
465            let (raster_band, rt_input) = RasterBand::from_wkb_string_little_endian(input, width, height)?;
466            input = rt_input;
467            raster_bands.push(raster_band);
468        }
469
470        Ok(Raster {
471            endian: Endian::Little,
472            version,
473            scale_x,
474            scale_y,
475            ip_x,
476            ip_y,
477            skew_x,
478            skew_y,
479            srid,
480            width,
481            height,
482            bands: raster_bands,
483        })
484    }
485
486    fn to_wkb_string_big_endian(self) -> String {
487
488        use crate::big_endian::*;
489
490        let mut string_bytes = Vec::new();
491
492        // endianness, byte, 1 byte
493        write_u8_be(&mut string_bytes, self.endian as u8);
494        // version, uint16, two bytes
495        write_u16_be(&mut string_bytes, self.version);            
496        // nBands, uint16, two bytes
497        write_u16_be(&mut string_bytes, self.bands.len() as u16);            
498        // write extents, 6x8 bytes       
499        write_f64_be(&mut string_bytes, self.scale_x);
500        write_f64_be(&mut string_bytes, self.scale_y);
501        write_f64_be(&mut string_bytes, self.ip_x);
502        write_f64_be(&mut string_bytes, self.ip_y);
503        write_f64_be(&mut string_bytes, self.skew_x);
504        write_f64_be(&mut string_bytes, self.skew_y);
505
506        // write srid
507        write_i32_be(&mut string_bytes, self.srid);
508        // write width
509        write_u16_be(&mut string_bytes, self.width);
510        // write height
511        write_u16_be(&mut string_bytes, self.height);
512
513        for band in self.bands {
514
515            // write band config (1 byte)    
516            let config = 0 |
517                (band.data.is_offline() as u8) << 7 |
518                (band.data.get_pixtype().has_nodata_value() as u8) << 6 |
519                (band.is_nodata_value as u8) << 5 |
520                (0_u8 << 4) |
521                band.data.get_pixtype().get_type() & 0b00001111;
522
523            write_u8_be(&mut string_bytes, config);
524
525            // write nodata value
526            string_bytes.append(&mut band.data.get_pixtype().get_nodata_value_as_string_big_endian());
527
528            // write raster data
529            string_bytes.append(&mut band.data.to_wkb_string_big_endian());
530        }
531
532        unsafe { String::from_utf8_unchecked(string_bytes) }
533    }
534
535    fn to_wkb_string_little_endian(self) -> String {
536        
537        use self::little_endian::*;
538
539        let mut string_bytes = Vec::new();
540
541        // endianness, byte, 1 byte
542        write_u8_le(&mut string_bytes, self.endian as u8);
543        // version, uint16, two bytes
544        write_u16_le(&mut string_bytes, self.version);            
545        // nBands, uint16, two bytes
546        write_u16_le(&mut string_bytes, self.bands.len() as u16);            
547        // write extents, 6x8 bytes       
548        write_f64_le(&mut string_bytes, self.scale_x);
549        write_f64_le(&mut string_bytes, self.scale_y);
550        write_f64_le(&mut string_bytes, self.ip_x);
551        write_f64_le(&mut string_bytes, self.ip_y);
552        write_f64_le(&mut string_bytes, self.skew_x);
553        write_f64_le(&mut string_bytes, self.skew_y);
554
555        // write srid
556        write_i32_le(&mut string_bytes, self.srid);
557        // write width
558        write_u16_le(&mut string_bytes, self.width);
559        // write height
560        write_u16_le(&mut string_bytes, self.height);
561
562        for band in self.bands {
563
564            // expected: 0x45 = 69 = 01000101
565            // got: 00 = 0 = 01000101
566
567            // write band config (1 byte)    
568            let config = 0 |
569                (band.data.is_offline() as u8) << 7 |
570                (band.data.get_pixtype().has_nodata_value() as u8) << 6 |
571                (band.is_nodata_value as u8) << 5 |
572                (0_u8 << 4) |
573                band.data.get_pixtype().get_type() & 0b00001111;
574
575            write_u8_le(&mut string_bytes, config);
576            
577            // write nodata value
578            string_bytes.append(&mut band.data.get_pixtype().get_nodata_value_as_string_little_endian());
579
580            // write raster data
581            string_bytes.append(&mut band.data.to_wkb_string_little_endian());
582        }
583
584        unsafe { String::from_utf8_unchecked(string_bytes) }
585    }
586}
587
588/// Endianness of the output string
589#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
590#[repr(u8)]
591pub enum Endian {
592    Big = 0,
593    Little = 1,
594}
595
596/// Single band of raster data
597#[derive(Debug, Clone, PartialEq, PartialOrd)]
598pub struct RasterBand {
599    /// If true, all the values of band are expected to be values. This is a dirty flagTo set the flag to its real
600    /// the function `st_bandisnodatamust` be called for the band 'TRUE' as last argument.          
601    pub is_nodata_value: bool,
602    /// The actual data of the 
603    pub data: RasterDataSource,
604}
605
606impl RasterBand {
607    
608    fn from_wkb_string_big_endian(input: &[u8], width: u16, height: u16) -> Result<(Self, &[u8]), ParseError> {
609        use crate::big_endian::*;
610        use self::ParseError::*;
611
612
613        let (pixinfo_bytes, mut input) = take_slice_1_byte(input)?;
614        let pixinfo = parse_u8_be(pixinfo_bytes);
615        let is_offline = ((pixinfo  & 0b10000000) >> 7) != 0;
616        let has_nodata_value = ((pixinfo  & 0b01000000) >> 6) != 0;
617        let is_nodata_value = ((pixinfo  & 0b00100000) >> 5) != 0; // ??
618        let pixtype = pixinfo & 0b00001111;
619
620
621        let pixtype = match pixtype {
622            0 => {
623                let nodata = if has_nodata_value { 
624                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
625                    input = pt_input;
626                    Some(parse_bool_be(nodata_bytes)?) 
627                } else { 
628                    let (_, pt_input) = take_slice_1_byte(input)?;
629                    input = pt_input;
630                    None 
631                };
632                PixType::Bool1Bit(nodata)
633            },
634            1 => {
635                let nodata = if has_nodata_value { 
636                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
637                    input = pt_input;
638                    Some(parse_u8_be(nodata_bytes)) 
639                } else { 
640                    let (_, pt_input) = take_slice_1_byte(input)?;
641                    input = pt_input;
642                    None 
643                };
644                PixType::UInt2(nodata)
645            },
646            2 => {
647                let nodata = if has_nodata_value { 
648                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
649                    input = pt_input;
650                    Some(parse_u8_be(nodata_bytes)) 
651                } else { 
652                    let (_, pt_input) = take_slice_1_byte(input)?;
653                    input = pt_input;
654                    None 
655                };
656                PixType::UInt4(nodata)
657            },
658            3 => {
659                let nodata = if has_nodata_value { 
660                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
661                    input = pt_input;
662                    Some(parse_i8_be(nodata_bytes)) 
663                } else { 
664                    let (_, pt_input) = take_slice_1_byte(input)?;
665                    input = pt_input;
666                    None 
667                };
668                PixType::Int8(nodata)
669            },
670            4 => {
671                let nodata = if has_nodata_value { 
672                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
673                    input = pt_input;
674                    Some(parse_u8_be(nodata_bytes)) 
675                } else { 
676                    let (_, pt_input) = take_slice_1_byte(input)?;
677                    input = pt_input;
678                    None 
679                };
680                PixType::UInt8(nodata)
681            },
682            5 => {
683                let nodata = if has_nodata_value { 
684                    let (nodata_bytes, pt_input) = take_slice_2_bytes(input)?;
685                    input = pt_input;
686                    Some(parse_i16_be(nodata_bytes)) 
687                } else { 
688                    let (_, pt_input) = take_slice_1_byte(input)?;
689                    input = pt_input;
690                    None 
691                };
692                PixType::Int16(nodata)
693            },
694            6 => {
695                let nodata = if has_nodata_value { 
696                    let (nodata_bytes, pt_input) = take_slice_2_bytes(input)?;
697                    input = pt_input;
698                    Some(parse_u16_be(nodata_bytes)) 
699                } else { 
700                    let (_, pt_input) = take_slice_1_byte(input)?;
701                    input = pt_input;
702                    None 
703                };
704                PixType::UInt16(nodata)
705            },
706            7 => {
707                let nodata = if has_nodata_value { 
708                    let (nodata_bytes, pt_input) = take_slice_4_bytes(input)?;
709                    input = pt_input;
710                    Some(parse_i32_be(nodata_bytes)) 
711                } else { 
712                    let (_, pt_input) = take_slice_1_byte(input)?;
713                    input = pt_input;
714                    None 
715                };
716                PixType::Int32(nodata)
717            },
718            8 => {
719                let nodata = if has_nodata_value { 
720                    let (nodata_bytes, pt_input) = take_slice_4_bytes(input)?;
721                    input = pt_input;
722                    Some(parse_u32_be(nodata_bytes)) 
723                } else { 
724                    let (_, pt_input) = take_slice_1_byte(input)?;
725                    input = pt_input;
726                    None 
727                };
728                PixType::UInt32(nodata)
729            },
730            10 => {
731                let nodata = if has_nodata_value { 
732                    let (nodata_bytes, pt_input) = take_slice_4_bytes(input)?;
733                    input = pt_input;
734                    Some(parse_f32_be(nodata_bytes)) 
735                } else { 
736                    let (_, pt_input) = take_slice_1_byte(input)?;
737                    input = pt_input;
738                    None 
739                };
740                PixType::Float32(nodata)
741            },
742            11 => {
743                let nodata = if has_nodata_value { 
744                    let (nodata_bytes, pt_input) = take_slice_8_bytes(input)?;
745                    input = pt_input;
746                    Some(parse_f64_be(nodata_bytes)) 
747                } else { 
748                    let (_, pt_input) = take_slice_1_byte(input)?;
749                    input = pt_input;
750                    None 
751                };
752                PixType::Float64(nodata)
753            }, 
754            other => return Err(InvalidPixelType(other)),
755        };
756
757
758        let (raster_data_source, input) = if is_offline {
759            RasterDataSource::parse_offline_big_endian(input, pixtype)?
760        } else {
761            RasterDataSource::parse_memory_big_endian(input, pixtype, width, height)?
762        };
763
764
765        Ok((RasterBand {
766            is_nodata_value,
767            data: raster_data_source,
768        }, input))
769    }
770
771    fn from_wkb_string_little_endian(input: &[u8], width: u16, height: u16) -> Result<(Self, &[u8]), ParseError> {
772        use crate::little_endian::*;
773        use self::ParseError::*;
774
775
776        let (pixinfo_bytes, mut input) = take_slice_1_byte(input)?;
777        let pixinfo = parse_u8_le(pixinfo_bytes);
778        let is_offline = ((pixinfo  & 0b10000000) >> 7) != 0;
779        let has_nodata_value = ((pixinfo  & 0b01000000) >> 6) != 0;
780        let is_nodata_value = ((pixinfo  & 0b00100000) >> 5) != 0; // ??
781        let pixtype = pixinfo & 0b00001111;
782
783
784        let pixtype = match pixtype {
785            0 => {
786                let nodata = if has_nodata_value { 
787                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
788                    input = pt_input;
789                    Some(parse_bool_le(nodata_bytes)?) 
790                } else { 
791                    let (_, pt_input) = take_slice_1_byte(input)?;
792                    input = pt_input;
793                    None 
794                };
795                PixType::Bool1Bit(nodata)
796            },
797            1 => {
798                let nodata = if has_nodata_value { 
799                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
800                    input = pt_input;
801                    Some(parse_u8_le(nodata_bytes)) 
802                } else { 
803                    let (_, pt_input) = take_slice_1_byte(input)?;
804                    input = pt_input;
805                    None 
806                };
807                PixType::UInt2(nodata)
808            },
809            2 => {
810                let nodata = if has_nodata_value { 
811                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
812                    input = pt_input;
813                    Some(parse_u8_le(nodata_bytes)) 
814                } else { 
815                    let (_, pt_input) = take_slice_1_byte(input)?;
816                    input = pt_input;
817                    None 
818                };
819                PixType::UInt4(nodata)
820            },
821            3 => {
822                let nodata = if has_nodata_value { 
823                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
824                    input = pt_input;
825                    Some(parse_i8_le(nodata_bytes)) 
826                } else { 
827                    let (_, pt_input) = take_slice_1_byte(input)?;
828                    input = pt_input;
829                    None 
830                };
831                PixType::Int8(nodata)
832            },
833            4 => {
834                let nodata = if has_nodata_value { 
835                    let (nodata_bytes, pt_input) = take_slice_1_byte(input)?;
836                    input = pt_input;
837                    Some(parse_u8_le(nodata_bytes)) 
838                } else { 
839                    let (_, pt_input) = take_slice_1_byte(input)?;
840                    input = pt_input;
841                    None 
842                };
843                PixType::UInt8(nodata)
844            },
845            5 => {
846                let nodata = if has_nodata_value { 
847                    let (nodata_bytes, pt_input) = take_slice_2_bytes(input)?;
848                    input = pt_input;
849                    Some(parse_i16_le(nodata_bytes)) 
850                } else { 
851                    let (_, pt_input) = take_slice_1_byte(input)?;
852                    input = pt_input;
853                    None 
854                };
855                PixType::Int16(nodata)
856            },
857            6 => {
858                let nodata = if has_nodata_value { 
859                    let (nodata_bytes, pt_input) = take_slice_2_bytes(input)?;
860                    input = pt_input;
861                    Some(parse_u16_le(nodata_bytes)) 
862                } else { 
863                    let (_, pt_input) = take_slice_1_byte(input)?;
864                    input = pt_input;
865                    None 
866                };
867                PixType::UInt16(nodata)
868            },
869            7 => {
870                let nodata = if has_nodata_value { 
871                    let (nodata_bytes, pt_input) = take_slice_4_bytes(input)?;
872                    input = pt_input;
873                    Some(parse_i32_le(nodata_bytes)) 
874                } else { 
875                    let (_, pt_input) = take_slice_1_byte(input)?;
876                    input = pt_input;
877                    None 
878                };
879                PixType::Int32(nodata)
880            },
881            8 => {
882                let nodata = if has_nodata_value { 
883                    let (nodata_bytes, pt_input) = take_slice_4_bytes(input)?;
884                    input = pt_input;
885                    Some(parse_u32_le(nodata_bytes)) 
886                } else { 
887                    let (_, pt_input) = take_slice_1_byte(input)?;
888                    input = pt_input;
889                    None 
890                };
891                PixType::UInt32(nodata)
892            },
893            10 => {
894                let nodata = if has_nodata_value { 
895                    let (nodata_bytes, pt_input) = take_slice_4_bytes(input)?;
896                    input = pt_input;
897                    Some(parse_f32_le(nodata_bytes)) 
898                } else { 
899                    let (_, pt_input) = take_slice_1_byte(input)?;
900                    input = pt_input;
901                    None 
902                };
903                PixType::Float32(nodata)
904            },
905            11 => {
906                let nodata = if has_nodata_value { 
907                    let (nodata_bytes, pt_input) = take_slice_8_bytes(input)?;
908                    input = pt_input;
909                    Some(parse_f64_le(nodata_bytes)) 
910                } else { 
911                    let (_, pt_input) = take_slice_1_byte(input)?;
912                    input = pt_input;
913                    None 
914                };
915                PixType::Float64(nodata)
916            }, 
917            other => return Err(InvalidPixelType(other)),
918        };
919
920        let (raster_data_source, input) = if is_offline {
921            RasterDataSource::parse_offline_little_endian(input, pixtype)?
922        } else {
923            RasterDataSource::parse_memory_little_endian(input, pixtype, width, height)?
924        };
925
926
927        Ok((RasterBand {
928            is_nodata_value,
929            data: raster_data_source,
930        }, input))
931    }
932}
933
934impl RasterDataSource {
935    
936    /// Returns `true` if the item is a `Offline { .. }` item
937    pub fn is_offline(&self) -> bool {
938        use self::RasterDataSource::*;
939        match self {
940            Offline(_) => true,
941            InMemory(_) => false,
942        }
943    }
944
945    pub fn get_pixtype(&self) -> PixType {
946        use self::RasterDataSource::*;
947        match &self {
948            Offline(o) => o.pixtype,
949            InMemory(i) => i.get_pixtype(),
950        }
951    }
952
953    fn parse_offline_big_endian(input: &[u8], pixtype: PixType) -> Result<(Self, &[u8]), ParseError> {
954        use crate::big_endian::*;
955        use std::ffi::CStr;
956
957        let (band_bytes, mut input) = take_slice_1_byte(input)?;
958        let band = parse_i8_be(band_bytes);
959
960        let mut path_bytes = Vec::new();
961        loop {
962
963            let (byte, new_input) = take_slice_1_byte(input)?;
964            input = new_input;
965            let parsed = parse_u8_be(byte);
966            path_bytes.push(parsed);
967
968            if parsed == b'\0' {
969                break; 
970            }
971        }
972
973        let path = CStr::from_bytes_with_nul(&path_bytes)
974        .map_err(|_| ParseError::FromBytesWithNulError(path_bytes.clone()))?;
975        let path = CString::from(path);
976        let path = PathBuf::from(path.clone().into_string()
977            .map_err(|_| ParseError::PathContainsNonUTF8Chars(path.to_owned()))?);
978        
979        Ok((RasterDataSource::Offline(OfflineRasterData {
980            band,
981            path,
982            pixtype,
983        }), input))
984
985    }
986
987    fn parse_offline_little_endian(input: &[u8], pixtype: PixType) -> Result<(Self, &[u8]), ParseError> {
988
989        use crate::little_endian::*;
990        use std::ffi::CStr;
991
992        let (band_bytes, mut input) = take_slice_1_byte(input)?;
993        let band = parse_i8_le(band_bytes);
994
995        let mut path_bytes = Vec::new();
996        loop {
997
998            let (byte, new_input) = take_slice_1_byte(input)?;
999            input = new_input;
1000            let parsed = parse_u8_le(byte);
1001            path_bytes.push(parsed);
1002
1003            if parsed == b'\0' {
1004                break; 
1005            }
1006        }
1007
1008        let path = CStr::from_bytes_with_nul(&path_bytes)
1009        .map_err(|_| ParseError::FromBytesWithNulError(path_bytes.clone()))?;
1010        let path = CString::from(path);
1011        let path = PathBuf::from(path.clone().into_string()
1012            .map_err(|_| ParseError::PathContainsNonUTF8Chars(path.to_owned()))?);
1013        
1014        Ok((RasterDataSource::Offline(OfflineRasterData {
1015            band,
1016            path,
1017            pixtype,
1018        }), input))
1019    }
1020
1021    fn parse_memory_big_endian(input: &[u8], pixtype: PixType, width: u16, height: u16) -> Result<(Self, &[u8]), ParseError> {
1022
1023
1024        parse_memory_data_fns!(
1025            crate::big_endian,
1026
1027            parse_memory_data_bool_be,
1028            parse_memory_data_uint2_be,
1029            parse_memory_data_uint4_be,
1030            parse_memory_data_int8_be,
1031            parse_memory_data_uint8_be,
1032            parse_memory_data_int16_be,
1033            parse_memory_data_uint16_be,
1034            parse_memory_data_int32_be,
1035            parse_memory_data_uint32_be,
1036            parse_memory_data_f32_be,
1037            parse_memory_data_f64_be,
1038
1039            parse_bool_be,
1040            parse_uint2_be,
1041            parse_uint4_be,
1042            parse_i8_be,
1043            parse_u8_be,
1044            parse_i16_be,
1045            parse_u16_be,
1046            parse_i32_be,
1047            parse_u32_be,
1048            parse_f32_be,
1049            parse_f64_be,
1050        );
1051
1052        let ret = gen_parse_function_body!(
1053            parse_memory_data_bool_be,
1054            parse_memory_data_uint2_be,
1055            parse_memory_data_uint4_be,
1056            parse_memory_data_int8_be,
1057            parse_memory_data_uint8_be,
1058            parse_memory_data_int16_be,
1059            parse_memory_data_uint16_be,
1060            parse_memory_data_int32_be,
1061            parse_memory_data_uint32_be,
1062            parse_memory_data_f32_be,
1063            parse_memory_data_f64_be,
1064
1065            input,
1066            pixtype,
1067            width,
1068            height,
1069        );
1070
1071        ret
1072    }
1073
1074    fn parse_memory_little_endian(input: &[u8], pixtype: PixType, width: u16, height: u16) -> Result<(Self, &[u8]), ParseError> {
1075        
1076
1077        parse_memory_data_fns!(
1078            crate::little_endian,
1079
1080            parse_memory_data_bool_le,
1081            parse_memory_data_uint2_le,
1082            parse_memory_data_uint4_le,
1083            parse_memory_data_int8_le,
1084            parse_memory_data_uint8_le,
1085            parse_memory_data_int16_le,
1086            parse_memory_data_uint16_le,
1087            parse_memory_data_int32_le,
1088            parse_memory_data_uint32_le,
1089            parse_memory_data_f32_le,
1090            parse_memory_data_f64_le,
1091
1092            parse_bool_le,
1093            parse_uint2_le,
1094            parse_uint4_le,
1095            parse_i8_le,
1096            parse_u8_le,
1097            parse_i16_le,
1098            parse_u16_le,
1099            parse_i32_le,
1100            parse_u32_le,
1101            parse_f32_le,
1102            parse_f64_le,
1103        );
1104
1105        let ret = gen_parse_function_body!(
1106            parse_memory_data_bool_le,
1107            parse_memory_data_uint2_le,
1108            parse_memory_data_uint4_le,
1109            parse_memory_data_int8_le,
1110            parse_memory_data_uint8_le,
1111            parse_memory_data_int16_le,
1112            parse_memory_data_uint16_le,
1113            parse_memory_data_int32_le,
1114            parse_memory_data_uint32_le,
1115            parse_memory_data_f32_le,
1116            parse_memory_data_f64_le,
1117            
1118            input,
1119            pixtype,
1120            width,
1121            height,
1122        );
1123
1124        ret
1125    }
1126}
1127
1128/// Pixel type + optional nodata value
1129#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
1130#[repr(u16)]
1131pub enum PixType {
1132    Bool1Bit(Option<bool>),
1133    UInt2(Option<u8>),
1134    UInt4(Option<u8>),
1135    Int8(Option<i8>),
1136    UInt8(Option<u8>),
1137    Int16(Option<i16>),
1138    UInt16(Option<u16>),
1139    Int32(Option<i32>),
1140    UInt32(Option<u32>),
1141    Float32(Option<f32>),
1142    Float64(Option<f64>),
1143}
1144
1145impl PixType {
1146    fn get_type(&self) -> u8 {
1147        use self::PixType::*;
1148        match self {
1149            Bool1Bit(_) => 0,
1150            UInt2(_) => 1,
1151            UInt4(_) => 2,
1152            Int8(_) => 3,
1153            UInt8(_) => 4,
1154            Int16(_) => 5,
1155            UInt16(_) => 6,
1156            Int32(_) => 7,
1157            UInt32(_) => 8, // no 9!
1158            Float32(_) => 10,
1159            Float64(_) => 11,  
1160        }
1161    }
1162
1163    pub fn has_nodata_value(&self) -> bool {
1164        use self::PixType::*;
1165        match self {
1166            | Bool1Bit(Some(_))
1167            | UInt2(Some(_))
1168            | UInt4(Some(_))
1169            | Int8(Some(_))
1170            | UInt8(Some(_))
1171            | Int16(Some(_))
1172            | UInt16(Some(_))
1173            | Int32(Some(_))
1174            | UInt32(Some(_))
1175            | Float32(Some(_))
1176            | Float64(Some(_)) => true,
1177            _ => false,
1178        }
1179    }
1180
1181    #[inline]
1182    fn get_nodata_value_as_string_big_endian(&self) -> Vec<u8> {
1183        
1184        use crate::big_endian::*;
1185        use self::PixType::*;
1186
1187        let mut s = Vec::new();
1188
1189        match self {
1190            Bool1Bit(Some(b)) =>    { write_bool_be(&mut s, *b); },
1191            UInt2(Some(b)) =>       { write_u8_be(&mut s, *b); /* TODO: u2! */ }, 
1192            UInt4(Some(b)) =>       { write_u8_be(&mut s, *b); /* TODO: u4! */ },
1193            Int8(Some(b)) =>        { write_i8_be(&mut s, *b); },
1194            UInt8(Some(b)) =>       { write_u8_be(&mut s, *b); }
1195            Int16(Some(b)) =>       { write_i16_be(&mut s, *b); }
1196            UInt16(Some(b)) =>      { write_u16_be(&mut s, *b); }
1197            Int32(Some(b)) =>       { write_i32_be(&mut s, *b); }
1198            UInt32(Some(b)) =>      { write_u32_be(&mut s, *b); }
1199            Float32(Some(b)) =>     { write_f32_be(&mut s, *b); }
1200            Float64(Some(b)) =>     { write_f64_be(&mut s, *b); }
1201            _ =>                    { write_u8_be(&mut s, 0); },
1202        }
1203
1204        s
1205    }
1206
1207    #[inline]
1208    fn get_nodata_value_as_string_little_endian(&self) -> Vec<u8> {
1209        
1210        use self::little_endian::*;
1211        use self::PixType::*;
1212
1213        let mut s = Vec::new();
1214
1215        match self {
1216            Bool1Bit(Some(b)) =>    { write_bool_le(&mut s, *b); },
1217            UInt2(Some(b)) =>       { write_u8_le(&mut s, *b); /* TODO: u2! */ }, 
1218            UInt4(Some(b)) =>       { write_u8_le(&mut s, *b); /* TODO: u4! */ },
1219            Int8(Some(b)) =>        { write_i8_le(&mut s, *b); },
1220            UInt8(Some(b)) =>       { write_u8_le(&mut s, *b); }
1221            Int16(Some(b)) =>       { write_i16_le(&mut s, *b); }
1222            UInt16(Some(b)) =>      { write_u16_le(&mut s, *b); }
1223            Int32(Some(b)) =>       { write_i32_le(&mut s, *b); }
1224            UInt32(Some(b)) =>      { write_u32_le(&mut s, *b); }
1225            Float32(Some(b)) =>     { write_f32_le(&mut s, *b); }
1226            Float64(Some(b)) =>     { write_f64_le(&mut s, *b); }
1227            _ =>                    { write_u8_le(&mut s, 0); },
1228        }
1229
1230        s
1231    }
1232}
1233
1234/// Source of the raster data bytes + pixel type definition
1235#[derive(Debug, Clone, PartialEq, PartialOrd)]
1236pub enum RasterDataSource {
1237    /// Pixel values are stored in an file
1238    Offline(OfflineRasterData),
1239    /// Pixels values, row after row, so pix[0] is upper-left, pix[w-1],is upper-right.
1240    /// As for endiannes, it is specified at the start of WKB, and up to 8bits 
1241    /// (bit-order is most significant first)
1242    InMemory(InMemoryRasterData),
1243}
1244
1245/// Raster data file source
1246#[derive(Debug, Clone, PartialEq, PartialOrd)]
1247pub struct OfflineRasterData {
1248    /// 0-based band number to use from the set available in the external file                             
1249    pub band: i8, 
1250    /// Path to data file
1251    pub path: PathBuf,
1252    /// Type of the pixels to read
1253    pub pixtype: PixType,
1254}
1255
1256/// In-memory raster data with nodata value and 
1257#[derive(Debug, Clone, PartialEq, PartialOrd)]
1258pub enum InMemoryRasterData {
1259    Bool1Bit { data: Vec<Vec<bool>>, nodata: Option<bool> },
1260    UInt2 { data: Vec<Vec<u8>>, nodata: Option<u8> },
1261    UInt4 { data: Vec<Vec<u8>>, nodata: Option<u8> },
1262    Int8 { data: Vec<Vec<i8>>, nodata: Option<i8> },
1263    UInt8 { data: Vec<Vec<u8>>, nodata: Option<u8> },
1264    Int16 { data: Vec<Vec<i16>>, nodata: Option<i16> },
1265    UInt16 { data: Vec<Vec<u16>>, nodata: Option<u16> },
1266    Int32 { data: Vec<Vec<i32>>, nodata: Option<i32> },
1267    UInt32 { data: Vec<Vec<u32>>, nodata: Option<u32> },
1268    Float32 { data: Vec<Vec<f32>>, nodata: Option<f32> },
1269    Float64 { data: Vec<Vec<f64>>, nodata: Option<f64> },
1270}
1271
1272impl InMemoryRasterData {
1273    /// Returns the pixtype of the `InMemoryRasterData`
1274    pub fn get_pixtype(&self) -> PixType {
1275        match &self {
1276            InMemoryRasterData::Bool1Bit { nodata, .. } => PixType::Bool1Bit(*nodata),
1277            InMemoryRasterData::UInt2 { nodata, .. } => PixType::UInt2(*nodata),
1278            InMemoryRasterData::UInt4 { nodata, .. } => PixType::UInt4(*nodata),
1279            InMemoryRasterData::Int8 { nodata, .. } => PixType::Int8(*nodata),
1280            InMemoryRasterData::UInt8 { nodata, .. } => PixType::UInt8(*nodata),
1281            InMemoryRasterData::Int16 { nodata, .. } => PixType::Int16(*nodata),
1282            InMemoryRasterData::UInt16 { nodata, .. } => PixType::UInt16(*nodata),
1283            InMemoryRasterData::Int32 { nodata, .. } => PixType::Int32(*nodata),
1284            InMemoryRasterData::UInt32 { nodata, .. } => PixType::UInt32(*nodata),
1285            InMemoryRasterData::Float32 { nodata, .. } => PixType::Float32(*nodata),
1286            InMemoryRasterData::Float64 { nodata, .. } => PixType::Float64(*nodata),
1287        }
1288    }
1289}
1290
1291impl RasterDataSource {
1292    
1293    /// Outputs the string to put in the SQL query (big endian)
1294    fn to_wkb_string_big_endian(self) -> Vec<u8> {
1295
1296        use self::RasterDataSource::*;
1297        use crate::big_endian::*;
1298
1299        let mut s = Vec::new();
1300
1301        match self {
1302            Offline(OfflineRasterData { band, path, .. }) => {
1303                // write band id
1304                write_i8_be(&mut s, band);
1305                // write file path
1306                let path: Vec<u8> = path.as_os_str().to_string_lossy().as_bytes().to_vec();
1307                let cstring = unsafe { CString::from_vec_unchecked(path) };
1308                for byte in cstring.to_bytes_with_nul() {
1309                    write_u8_be(&mut s, *byte);
1310                }
1311            },
1312            InMemory(data) => {
1313                match data {
1314                    InMemoryRasterData::Bool1Bit { data, .. }   => { for row in data { for byte in row { write_bool_be(&mut s, byte); } } },
1315                    InMemoryRasterData::UInt2 { data, .. }      => { for row in data { for byte in row { write_u8_be(&mut s, byte); } } },
1316                    InMemoryRasterData::UInt4 { data, .. }      => { for row in data { for byte in row { write_u8_be(&mut s, byte); } } },
1317                    InMemoryRasterData::Int8 { data, .. }       => { for row in data { for byte in row { write_i8_be(&mut s, byte); } } },
1318                    InMemoryRasterData::UInt8 { data, .. }      => { for row in data { for byte in row { write_u8_be(&mut s, byte); } } },
1319                    InMemoryRasterData::Int16 { data, .. }      => { for row in data { for byte in row { write_i16_be(&mut s, byte); } } },
1320                    InMemoryRasterData::UInt16 { data, .. }     => { for row in data { for byte in row { write_u16_be(&mut s, byte); } } },
1321                    InMemoryRasterData::Int32 { data, .. }      => { for row in data { for byte in row { write_i32_be(&mut s, byte); } } },
1322                    InMemoryRasterData::UInt32 { data, .. }     => { for row in data { for byte in row { write_u32_be(&mut s, byte); } } },
1323                    InMemoryRasterData::Float32 { data, .. }    => { for row in data { for byte in row { write_f32_be(&mut s, byte); } } },
1324                    InMemoryRasterData::Float64 { data, .. }    => { for row in data { for byte in row { write_f64_be(&mut s, byte); } } },
1325                }
1326            },
1327        }
1328
1329        s
1330    }
1331
1332    /// Outputs the string to put in the SQL query (little endian)
1333    fn to_wkb_string_little_endian(self) -> Vec<u8> {
1334
1335        use self::RasterDataSource::*;
1336        use self::little_endian::*;
1337
1338        let mut s = Vec::new();
1339
1340        match self {
1341            Offline(OfflineRasterData { band, path, .. }) => {
1342                // write band id
1343                write_i8_le(&mut s, band);
1344                // write file path
1345                let path: Vec<u8> = path.as_os_str().to_string_lossy().as_bytes().to_vec();
1346                let cstring = unsafe { CString::from_vec_unchecked(path) };
1347                for byte in cstring.into_bytes_with_nul() {
1348                    let byte: u8 = byte; // rustc is dumb
1349                    write_u8_le(&mut s, byte);
1350                }
1351            },
1352            InMemory(data) => {
1353                match data {
1354                    InMemoryRasterData::Bool1Bit { data, .. }   => { for row in data { for byte in row { write_bool_le(&mut s, byte); } } },
1355                    InMemoryRasterData::UInt2 { data, .. }      => { for row in data { for byte in row { write_u8_le(&mut s, byte); } } },
1356                    InMemoryRasterData::UInt4 { data, .. }      => { for row in data { for byte in row { write_u8_le(&mut s, byte); } } },
1357                    InMemoryRasterData::Int8 { data, .. }       => { for row in data { for byte in row { write_i8_le(&mut s, byte); } } },
1358                    InMemoryRasterData::UInt8 { data, .. }      => { for row in data { for byte in row { write_u8_le(&mut s, byte); } } },
1359                    InMemoryRasterData::Int16 { data, .. }      => { for row in data { for byte in row { write_i16_le(&mut s, byte); } } },
1360                    InMemoryRasterData::UInt16 { data, .. }     => { for row in data { for byte in row { write_u16_le(&mut s, byte); } } },
1361                    InMemoryRasterData::Int32 { data, .. }      => { for row in data { for byte in row { write_i32_le(&mut s, byte); } } },
1362                    InMemoryRasterData::UInt32 { data, .. }     => { for row in data { for byte in row { write_u32_le(&mut s, byte); } } },
1363                    InMemoryRasterData::Float32 { data, .. }    => { for row in data { for byte in row { write_f32_le(&mut s, byte); } } },
1364                    InMemoryRasterData::Float64 { data, .. }    => { for row in data { for byte in row { write_f64_le(&mut s, byte); } } },
1365                }
1366            },
1367        }
1368
1369        s
1370    }
1371}