You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: lib.rs
    path of file: ./repos/parity-ethereum/ethcore/engines/clique/src
    
    the code of the file until where you have to start completion: // Copyright 2015-2020 Parity Technologies (UK) Ltd.
// This file is part of Parity Ethereum.

// Parity Ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity Ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity Ethereum.  If not, see <http://www.gnu.org/licenses/>.

//! Implementation of the Clique PoA Engine.
//!
//! File structure:
//! - mod.rs -> Provides the engine API implementation, with additional block state tracking
//! - block_state.rs -> Records the Clique state for given block.
//! - params.rs -> Contains the parameters for the Cli
    
	fn state(&self, header: &Header) -> Result<CliqueBlockState, Error> {
		let mut block_state_by_hash = self.block_state_by_hash.write();
		if let Some(state) = block_state_by_hash.get_mut(&header.hash()) {
			return Ok(state.clone());
		}
		// If we are looking for an checkpoint block state, we can directly reconstruct it.
		if header.number() % self.epoch_length == 0 {
			let state = self.new_checkpoint_state(header)?;
			block_state_by_hash.insert(header.hash(), state.clone());
			return Ok(state);
		}
		// BlockState is not found in memory, which means we need to reconstruct state from last checkpoint.
		match self.client.read().as_ref().and_then(|w| w.upgrade()) {
			None => {
				return Err(EngineError::RequiresClient)?;
			}
			Some(c) => {
				let last_checkpoint_number = header.number() - header.number() % self.epoch_length as u64;
				debug_assert_ne!(last_checkpoint_number, header.number());

				// Catching up state, note that we don't really store block state for intermediary blocks,
				// for speed.
				let backfill_start = time::Instant::now();
				trace!(target: "engine",
						"Back-filling block state. last_checkpoint_number: {}, target: {}({}).",
						last_checkpoint_number, header.number(), header.hash());

				let mut chain = VecDeque::with_capacity((header.number() - last_checkpoint_number + 1) as usize);

				// Put ourselves in.
				chain.push_front(header.clone());

				// populate chain to last checkpoint
				loop {
					let (last_parent_hash, last_num) = {
						let l = chain.front().expect("chain has at least one element; qed");
						(*l.parent_hash(), l.number())
					};

					if last_num == last_checkpoint_number + 1 {
						break;
					}
					match c.block_header(BlockId::Hash(last_parent_hash)) {
						None => {
							return Err(BlockError::UnknownParent(last_parent_hash))?;
						}
						Some(next) => {
							chain.push_front(next.decode()?);
						}
					}
				}

				// Get the state for last checkpoint.
				let last_checkpoint_hash = *chain.front()
					.expect("chain has at least one element; qed")
					.parent_hash();

				let last_checkpoint_header = match c.block_header(BlockId::Hash(last_checkpoint_hash)) {
					None => return Err(EngineError::CliqueMissingCheckpoint(last_checkpoint_hash))?,
					Some(header) => header.decode()?,
				};

				let last_checkpoint_state = match block_state_by_hash.get_mut(&last_checkpoint_hash) {
					Some(state) => state.clone(),
					None => self.new_checkpoint_state(&last_checkpoint_header)?,
				};

				block_state_by_hash.insert(last_checkpoint_header.hash(), last_checkpoint_state.clone());

				// Backfill!
				let mut new_state = last_checkpoint_state.clone();
				for item in &chain {
					new_state.apply(item, false)?;
				}
				new_state.calc_next_timestamp(header.timestamp(), self.period)?;
				block_state_by_hash.insert(header.hash(), new_state.clone());

				let elapsed = backfill_start.elapsed();
				trace!(target: "engine", "Back-filling succeed, took {} ms.", elapsed.as_millis());
				Ok(new_state)
			}
		}
	}