1 // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 // SPDX-License-Identifier: Apache-2.0 3 4 use std::{io::copy, io::prelude::*}; 5 6 use failure::Error; 7 use log::info; 8 use rmp_serde::Serializer; 9 use serde::Serialize; 10 11 use crate::store::base::Store; 12 13 const CACHE_VERSION: &[u8] = b"askalono-04"; 14 15 impl Store { 16 /// Create a store from a cache file. 17 /// 18 /// This method is highly useful for quickly loading a cache, as creating 19 /// one from text data is rather slow. This method can typically load 20 /// the full SPDX set from disk in 200-300 ms. The cache will be 21 /// sanity-checked to ensure it was generated with a similar version of 22 /// askalono. from_cache<R>(mut readable: R) -> Result<Store, Error> where R: Read + Sized,23 pub fn from_cache<R>(mut readable: R) -> Result<Store, Error> 24 where 25 R: Read + Sized, 26 { 27 let mut header = [0u8; 11]; 28 readable.read_exact(&mut header)?; 29 30 if header != CACHE_VERSION { 31 failure::bail!("cache version mismatch"); 32 } 33 34 #[cfg(not(feature = "gzip"))] 35 let dec = zstd::Decoder::new(readable)?; 36 #[cfg(feature = "gzip")] 37 let dec = flate2::read::GzDecoder::new(readable); 38 39 let store = rmp_serde::decode::from_read(dec)?; 40 Ok(store) 41 } 42 43 /// Serialize the current store. 44 /// 45 /// The output will be a MessagePack'd gzip'd or zstd'd binary stream that should be 46 /// written to disk. to_cache<W>(&self, mut writable: W) -> Result<(), Error> where W: Write + Sized,47 pub fn to_cache<W>(&self, mut writable: W) -> Result<(), Error> 48 where 49 W: Write + Sized, 50 { 51 let buf = { 52 // This currently sits around 3.7MiB, so go up to 4 to fit comfortably 53 let mut buf = Vec::with_capacity(4 * 1024 * 1024); 54 let mut serializer = Serializer::new(&mut buf); 55 self.serialize(&mut serializer)?; 56 buf 57 }; 58 59 info!("Pre-compressed output is {} bytes", buf.len()); 60 61 writable.write_all(CACHE_VERSION)?; 62 63 #[cfg(not(feature = "gzip"))] 64 let mut enc = zstd::Encoder::new(writable, 21)?; 65 #[cfg(feature = "gzip")] 66 let mut enc = flate2::write::GzEncoder::new(writable, flate2::Compression::default()); 67 68 copy(&mut buf.as_slice(), &mut enc)?; 69 enc.finish()?; 70 71 Ok(()) 72 } 73 } 74