fc_cli/frontier_db_cmd/
utils.rs

1// This file is part of Frontier.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
5
6// This program is free software: you can redistribute it and/or modify
7// it under the terms of the GNU General Public License as published by
8// the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10
11// This program is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU General Public License for more details.
15
16// You should have received a copy of the GNU General Public License
17// along with this program. If not, see <https://www.gnu.org/licenses/>.
18
19#![allow(clippy::format_in_format_args)]
20
21use std::{
22	fs,
23	io::{self, Read},
24	path::PathBuf,
25};
26
27use serde::de::DeserializeOwned;
28use serde_json::Deserializer;
29// Substrate
30use sp_runtime::traits::Block as BlockT;
31
32use super::{DbValue, Operation};
33
34pub fn maybe_deserialize_value<B: BlockT>(
35	operation: &Operation,
36	value: Option<&PathBuf>,
37) -> sc_cli::Result<Option<DbValue<B::Hash>>> {
38	fn parse_db_values<H: DeserializeOwned, I: Read + Send>(
39		input: I,
40	) -> sc_cli::Result<Option<DbValue<H>>> {
41		let mut stream_deser = Deserializer::from_reader(input).into_iter::<DbValue<H>>();
42		if let Some(Ok(value)) = stream_deser.next() {
43			Ok(Some(value))
44		} else {
45			Err("Failed to deserialize value data".into())
46		}
47	}
48
49	if let Operation::Create | Operation::Update = operation {
50		match &value {
51			Some(filename) => parse_db_values::<B::Hash, _>(fs::File::open(filename)?),
52			None => {
53				let mut buffer = String::new();
54				let res = parse_db_values(io::stdin());
55				let _ = io::stdin().read_line(&mut buffer);
56				res
57			}
58		}
59	} else {
60		Ok(None)
61	}
62}
63
64/// Messaging and prompt.
65pub trait FrontierDbMessage {
66	fn key_value_error<K: core::fmt::Debug, V: core::fmt::Debug>(
67		&self,
68		key: K,
69		value: &V,
70	) -> sc_cli::Error {
71		format!("Key `{key:?}` and Value `{value:?}` are not compatible with this operation").into()
72	}
73
74	fn key_column_error<K: core::fmt::Debug, V: core::fmt::Debug>(
75		&self,
76		key: K,
77		value: &V,
78	) -> sc_cli::Error {
79		format!("Key `{key:?}` and Column `{value:?}` are not compatible with this operation")
80			.into()
81	}
82
83	fn key_not_empty_error<K: core::fmt::Debug>(&self, key: K) -> sc_cli::Error {
84		format!("Operation not allowed for non-empty Key `{key:?}`").into()
85	}
86
87	#[cfg(not(test))]
88	fn confirmation_prompt<K: core::fmt::Debug, V: core::fmt::Debug>(
89		&self,
90		operation: &Operation,
91		key: K,
92		existing_value: &V,
93		new_value: &V,
94	) -> sc_cli::Result<()> {
95		println!(
96			"{}",
97			format!(
98				r#"
99			---------------------------------------------
100			Operation: {:?}
101			Key: {:?}
102			Existing value: {:?}
103			New value: {:?}
104			---------------------------------------------
105			Type `confirm` and press [Enter] to confirm:
106		"#,
107				operation, key, existing_value, new_value
108			)
109		);
110
111		let mut buffer = String::new();
112		io::stdin().read_line(&mut buffer)?;
113		if buffer.trim() != "confirm" {
114			return Err("-- Cancel exit --".into());
115		}
116		Ok(())
117	}
118
119	#[cfg(test)]
120	fn confirmation_prompt<K: core::fmt::Debug, V: core::fmt::Debug>(
121		&self,
122		_operation: &Operation,
123		_key: K,
124		_existing_value: &V,
125		_new_value: &V,
126	) -> sc_cli::Result<()> {
127		Ok(())
128	}
129}