1use core::fmt::{Debug, Display};
2
3use alloc::{
4 boxed::Box,
5 format,
6 string::{String, ToString},
7 vec::Vec,
8};
9use encoding::Encoding;
10
11use crate::{LooseParser, PaymentParser, RequisiteToleranceParser, StrictParser};
12
13use super::{
14 string_types::{ExactSizeString, MaxSizeString, StringExt},
15 CustomRequisites, NoCustomRequisites,
16};
17
18pub(super) const FORMAT_ID_BYTES: [u8; 2] = [b'S', b'T'];
19pub(super) const VERSION_0001_BYTES: [u8; 4] = [b'0', b'0', b'0', b'1'];
20
21#[derive(Clone, Debug, PartialEq, Eq)]
23pub struct Payment<T: CustomRequisites = NoCustomRequisites> {
24 pub(super) header: PaymentHeader,
25 pub(super) requisites: Vec<Requisite<T>>,
26}
27
28#[derive(Debug)]
29pub struct PaymentBuilder<T: CustomRequisites = NoCustomRequisites> {
30 payment: Payment<T>,
31}
32
33impl<T: CustomRequisites> PaymentBuilder<T> {
34 pub fn with_version(mut self, version: [u8; 4]) -> Self {
36 self.payment.header.version = version;
37 self
38 }
39
40 pub fn with_encdoing(mut self, encdoing: PaymentEncoding) -> Self {
42 self.payment.header.encoding = encdoing;
43 self
44 }
45
46 pub fn with_separator(mut self, separator: char) -> Self {
48 assert!(separator.is_ascii());
49
50 self.payment.header.separator = separator as u8;
51 self
52 }
53
54 pub fn with_additional_requisites(
56 mut self,
57 requisites: impl IntoIterator<Item = Requisite<T>>,
58 ) -> Self {
59 let requisites = requisites.into_iter().inspect(|requisite| {
60 assert!(!matches!(requisite, Requisite::Name(_)));
61 assert!(!matches!(requisite, Requisite::PersonalAcc(_)));
62 assert!(!matches!(requisite, Requisite::BankName(_)));
63 assert!(!matches!(requisite, Requisite::BIC(_)));
64 assert!(!matches!(requisite, Requisite::CorrespAcc(_)));
65 });
66
67 self.payment.requisites.extend(requisites);
68 self
69 }
70
71 pub fn build(self) -> Payment<T> {
73 self.payment
74 }
75}
76
77impl<T: CustomRequisites> Default for PaymentBuilder<T> {
78 fn default() -> Self {
79 Self {
80 payment: Payment {
81 header: PaymentHeader {
82 format_id: FORMAT_ID_BYTES,
83 version: VERSION_0001_BYTES,
84 encoding: PaymentEncoding::Utf8,
85 separator: b'|',
86 },
87 requisites: Vec::with_capacity(16),
88 },
89 }
90 }
91}
92
93impl Payment {
94 pub fn builder(requisites: RequiredRequisite) -> PaymentBuilder {
96 let mut builder = PaymentBuilder::default();
97
98 let required_requisites = alloc::vec![
99 Requisite::Name(requisites.name),
100 Requisite::PersonalAcc(requisites.personal_acc),
101 Requisite::BankName(requisites.bank_name),
102 Requisite::BIC(requisites.bic),
103 Requisite::CorrespAcc(requisites.correstp_acc),
104 ];
105
106 builder.payment.requisites = required_requisites;
107
108 builder
109 }
110
111 pub fn parser() -> PaymentParser {
113 PaymentParser::default()
114 }
115
116 pub fn requisite_tolerance_parser() -> PaymentParser<RequisiteToleranceParser> {
118 PaymentParser::default()
119 }
120
121 pub fn loose_parser() -> PaymentParser<LooseParser> {
123 PaymentParser::default()
124 }
125}
126
127impl<T: CustomRequisites> Payment<T> {
128 pub fn custom_builder(requisites: RequiredRequisite) -> PaymentBuilder<T> {
130 let mut builder = PaymentBuilder::<T>::default();
131
132 let required_requisites = alloc::vec![
133 Requisite::Name(requisites.name),
134 Requisite::PersonalAcc(requisites.personal_acc),
135 Requisite::BankName(requisites.bank_name),
136 Requisite::BIC(requisites.bic),
137 Requisite::CorrespAcc(requisites.correstp_acc),
138 ];
139
140 builder.payment.requisites = required_requisites;
141
142 builder
143 }
144
145 pub fn custom_parser() -> PaymentParser<StrictParser, T> {
147 PaymentParser::default()
148 }
149
150 pub fn requisite_tolerance_custom_parser() -> PaymentParser<RequisiteToleranceParser, T> {
152 PaymentParser::default()
153 }
154
155 pub fn loose_custom_parser() -> PaymentParser<LooseParser, T> {
157 PaymentParser::default()
158 }
159
160 pub fn to_bytes(&self) -> super::Result<Vec<u8>> {
162 let mut buffer = Vec::with_capacity(308);
163 self.write_to(&mut buffer)?;
164 Ok(buffer)
165 }
166
167 pub fn write_to(&self, buffer: &mut Vec<u8>) -> super::Result<()> {
169 buffer.push(self.header.format_id[0]);
171 buffer.push(self.header.format_id[1]);
172
173 buffer.push(self.header.version[0]);
174 buffer.push(self.header.version[1]);
175 buffer.push(self.header.version[2]);
176 buffer.push(self.header.version[3]);
177
178 buffer.push(self.header.encoding as u8);
179
180 for requisite in &self.requisites {
182 buffer.push(self.header.separator);
183 buffer.extend(self.encode_requisite(requisite)?);
184 }
185
186 Ok(())
187 }
188
189 pub fn to_utf8_lossy(&self) -> super::Result<String> {
191 let bytes = self.to_bytes()?;
192 Ok(String::from_utf8_lossy(&bytes).to_string())
193 }
194
195 pub fn get(&self, key: &str) -> Option<&str> {
197 self.requisites
198 .iter()
199 .find(|req| req.key() == key)
200 .map(|req| req.value())
201 }
202
203 pub fn header(&self) -> &PaymentHeader {
205 &self.header
206 }
207
208 pub fn requisites(&self) -> impl Iterator<Item = &Requisite<T>> {
210 self.requisites.iter()
211 }
212}
213
214impl<T: CustomRequisites> Payment<T> {
215 fn encode_requisite(&self, req: &Requisite<T>) -> super::Result<Vec<u8>> {
216 let pair = format!("{}={}", req.key(), req.value());
217 match self.header.encoding {
218 PaymentEncoding::Win1251 => encoding::all::WINDOWS_1251
219 .encode(&pair, encoding::EncoderTrap::Strict)
220 .map_err(|_| super::Error::EncodingError),
221 PaymentEncoding::Utf8 => Ok(pair.into_bytes()),
222 PaymentEncoding::Koi8R => encoding::all::KOI8_R
223 .encode(&pair, encoding::EncoderTrap::Strict)
224 .map_err(|_| super::Error::EncodingError),
225 }
226 }
227}
228
229impl<T: CustomRequisites> Display for Payment<T> {
230 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
231 Display::fmt(&self.header, f)?;
232
233 for req in self.requisites.iter() {
234 write!(f, "{}", self.header.separator())?;
235 Display::fmt(req, f)?;
236 }
237
238 Ok(())
239 }
240}
241
242#[derive(Clone, Debug, PartialEq, Eq)]
244pub struct PaymentHeader {
245 pub(super) format_id: [u8; 2],
247
248 pub(super) version: [u8; 4],
250
251 pub(super) encoding: PaymentEncoding,
253
254 pub(super) separator: u8,
256}
257
258impl PaymentHeader {
259 pub fn format_id(&self) -> [char; 2] {
261 [self.format_id[0] as char, self.format_id[1] as char]
262 }
263
264 pub fn version(&self) -> [char; 4] {
266 [
267 self.version[0] as char,
268 self.version[1] as char,
269 self.version[2] as char,
270 self.version[3] as char,
271 ]
272 }
273
274 pub fn encoding(&self) -> PaymentEncoding {
276 self.encoding
277 }
278
279 pub fn separator(&self) -> char {
281 self.separator as char
282 }
283}
284
285impl Display for PaymentHeader {
286 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
287 write!(
288 f,
289 "{}{}{}{}{}{}{}",
290 self.format_id[0] as char,
291 self.format_id[1] as char,
292 self.version[0] as char,
293 self.version[1] as char,
294 self.version[2] as char,
295 self.version[3] as char,
296 self.encoding as u8 as char,
297 )
298 }
299}
300
301#[derive(Clone, Debug, PartialEq, Eq)]
303pub struct RequiredRequisite {
304 pub name: MaxSizeString<160>,
305 pub personal_acc: ExactSizeString<20>,
306 pub bank_name: MaxSizeString<45>,
307 pub bic: ExactSizeString<9>,
308 pub correstp_acc: MaxSizeString<20>,
309}
310
311#[derive(Clone, Debug, PartialEq, Eq)]
313pub enum Requisite<T: CustomRequisites> {
314 Name(MaxSizeString<160>),
317
318 PersonalAcc(ExactSizeString<20>),
320
321 BankName(MaxSizeString<45>),
323
324 BIC(ExactSizeString<9>),
326
327 CorrespAcc(MaxSizeString<20>),
329
330 Sum(MaxSizeString<18>),
333
334 Purpose(MaxSizeString<210>),
336
337 PayeeINN(MaxSizeString<12>),
339
340 PayerINN(MaxSizeString<12>),
342
343 DrawerStatus(MaxSizeString<2>),
345
346 KPP(MaxSizeString<9>),
348
349 CBC(MaxSizeString<20>),
351
352 OKTMO(MaxSizeString<11>),
354
355 PaytReason(MaxSizeString<2>),
357
358 TaxPeriod(MaxSizeString<10>),
360
361 DocNo(MaxSizeString<15>),
363
364 DocDate(MaxSizeString<10>),
366
367 TaxPayKind(MaxSizeString<2>),
369
370 LastName(Box<str>),
373
374 FirstName(Box<str>),
376
377 MiddleName(Box<str>),
379
380 PayerAddress(Box<str>),
382
383 PersonalAccount(Box<str>),
385
386 DocIdx(Box<str>),
388
389 PensAcc(Box<str>),
391
392 Contract(Box<str>),
394
395 PersAcc(Box<str>),
397
398 Flat(Box<str>),
400
401 Phone(Box<str>),
403
404 PayerIdType(Box<str>),
406
407 PayerIdNum(Box<str>),
409
410 ChildFio(Box<str>),
412
413 BirthDate(Box<str>),
415
416 PaymTerm(Box<str>),
418
419 PaymPeriod(Box<str>),
421
422 Category(Box<str>),
424
425 ServiceName(Box<str>),
427
428 CounterId(Box<str>),
430
431 CounterVal(Box<str>),
433
434 QuittId(Box<str>),
436
437 QuittDate(Box<str>),
439
440 InstNum(Box<str>),
442
443 ClassNum(Box<str>),
445
446 SpecFio(Box<str>),
448
449 AddAmount(Box<str>),
451
452 RuleId(Box<str>),
454
455 ExecId(Box<str>),
457
458 RegType(Box<str>),
460
461 UIN(Box<str>),
463
464 TechCode(TechCode),
466
467 Custom(T),
469}
470
471impl<T: CustomRequisites> Requisite<T> {
472 pub fn key(&self) -> &str {
473 match self {
474 Requisite::Name(_) => "Name",
475 Requisite::PersonalAcc(_) => "PersonalAcc",
476 Requisite::BankName(_) => "BankName",
477 Requisite::BIC(_) => "BIC",
478 Requisite::CorrespAcc(_) => "CorrespAcc",
479 Requisite::Sum(_) => "Sum",
480 Requisite::Purpose(_) => "Purpose",
481 Requisite::PayeeINN(_) => "PayeeINN",
482 Requisite::PayerINN(_) => "PayerINN",
483 Requisite::DrawerStatus(_) => "DrawerStatus",
484 Requisite::KPP(_) => "KPP",
485 Requisite::CBC(_) => "CBC",
486 Requisite::OKTMO(_) => "OKTMO",
487 Requisite::PaytReason(_) => "PaytReason",
488 Requisite::TaxPeriod(_) => "TaxPeriod",
489 Requisite::DocNo(_) => "DocNo",
490 Requisite::DocDate(_) => "DocDate",
491 Requisite::TaxPayKind(_) => "TaxPayKind",
492 Requisite::LastName(_) => "LastName",
493 Requisite::FirstName(_) => "FirstName",
494 Requisite::MiddleName(_) => "MiddleName",
495 Requisite::PayerAddress(_) => "PayerAddress",
496 Requisite::PersonalAccount(_) => "PersonalAccount",
497 Requisite::DocIdx(_) => "DocIdx",
498 Requisite::PensAcc(_) => "PensAcc",
499 Requisite::Contract(_) => "Contract",
500 Requisite::PersAcc(_) => "PersAcc",
501 Requisite::Flat(_) => "Flat",
502 Requisite::Phone(_) => "Phone",
503 Requisite::PayerIdType(_) => "PayerIdType",
504 Requisite::PayerIdNum(_) => "PayerIdNum",
505 Requisite::ChildFio(_) => "ChildFio",
506 Requisite::BirthDate(_) => "BirthDate",
507 Requisite::PaymTerm(_) => "PaymTerm",
508 Requisite::PaymPeriod(_) => "PaymPeriod",
509 Requisite::Category(_) => "Category",
510 Requisite::ServiceName(_) => "ServiceName",
511 Requisite::CounterId(_) => "CounterId",
512 Requisite::CounterVal(_) => "CounterVal",
513 Requisite::QuittId(_) => "QuittId",
514 Requisite::QuittDate(_) => "QuittDate",
515 Requisite::InstNum(_) => "InstNum",
516 Requisite::ClassNum(_) => "ClassNum",
517 Requisite::SpecFio(_) => "SpecFio",
518 Requisite::AddAmount(_) => "AddAmount",
519 Requisite::RuleId(_) => "RuleId",
520 Requisite::ExecId(_) => "ExecId",
521 Requisite::RegType(_) => "RegType",
522 Requisite::UIN(_) => "UIN",
523 Requisite::TechCode(_) => "TechCode",
524 Requisite::Custom(v) => v.key(),
525 }
526 }
527
528 pub fn value(&self) -> &str {
529 match self {
530 Requisite::Name(v) => v,
531 Requisite::PersonalAcc(v) => v,
532 Requisite::BankName(v) => v,
533 Requisite::BIC(v) => v,
534 Requisite::CorrespAcc(v) => v,
535 Requisite::Sum(v) => v,
536 Requisite::Purpose(v) => v,
537 Requisite::PayeeINN(v) => v,
538 Requisite::PayerINN(v) => v,
539 Requisite::DrawerStatus(v) => v,
540 Requisite::KPP(v) => v,
541 Requisite::CBC(v) => v,
542 Requisite::OKTMO(v) => v,
543 Requisite::PaytReason(v) => v,
544 Requisite::TaxPeriod(v) => v,
545 Requisite::DocNo(v) => v,
546 Requisite::DocDate(v) => v,
547 Requisite::TaxPayKind(v) => v,
548 Requisite::LastName(v) => v,
549 Requisite::FirstName(v) => v,
550 Requisite::MiddleName(v) => v,
551 Requisite::PayerAddress(v) => v,
552 Requisite::PersonalAccount(v) => v,
553 Requisite::DocIdx(v) => v,
554 Requisite::PensAcc(v) => v,
555 Requisite::Contract(v) => v,
556 Requisite::PersAcc(v) => v,
557 Requisite::Flat(v) => v,
558 Requisite::Phone(v) => v,
559 Requisite::PayerIdType(v) => v,
560 Requisite::PayerIdNum(v) => v,
561 Requisite::ChildFio(v) => v,
562 Requisite::BirthDate(v) => v,
563 Requisite::PaymTerm(v) => v,
564 Requisite::PaymPeriod(v) => v,
565 Requisite::Category(v) => v,
566 Requisite::ServiceName(v) => v,
567 Requisite::CounterId(v) => v,
568 Requisite::CounterVal(v) => v,
569 Requisite::QuittId(v) => v,
570 Requisite::QuittDate(v) => v,
571 Requisite::InstNum(v) => v,
572 Requisite::ClassNum(v) => v,
573 Requisite::SpecFio(v) => v,
574 Requisite::AddAmount(v) => v,
575 Requisite::RuleId(v) => v,
576 Requisite::ExecId(v) => v,
577 Requisite::RegType(v) => v,
578 Requisite::UIN(v) => v,
579 Requisite::TechCode(tech_code) => tech_code.as_str(),
580 Requisite::Custom(v) => v.value(),
581 }
582 }
583}
584
585impl<T: CustomRequisites> TryFrom<(&str, &str)> for Requisite<T> {
586 type Error = super::Error;
587
588 fn try_from((key, val): (&str, &str)) -> super::Result<Self> {
589 let requisite = match key {
590 "Name" => Requisite::Name(
591 val.to_max_size()
592 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
593 ),
594 "PersonalAcc" => Requisite::PersonalAcc(
595 val.to_exact_size()
596 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
597 ),
598 "BankName" => Requisite::BankName(
599 val.to_max_size()
600 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
601 ),
602 "BIC" => Requisite::BIC(
603 val.to_exact_size()
604 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
605 ),
606 "CorrespAcc" => Requisite::CorrespAcc(
607 val.to_max_size()
608 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
609 ),
610 "Sum" => Requisite::Sum(
611 val.to_max_size()
612 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
613 ),
614 "Purpose" => Requisite::Purpose(
615 val.to_max_size()
616 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
617 ),
618 "PayeeINN" => Requisite::PayeeINN(
619 val.to_max_size()
620 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
621 ),
622 "PayerINN" => Requisite::PayerINN(
623 val.to_max_size()
624 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
625 ),
626 "DrawerStatus" => Requisite::DrawerStatus(
627 val.to_max_size()
628 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
629 ),
630 "KPP" => Requisite::KPP(
631 val.to_max_size()
632 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
633 ),
634 "CBC" => Requisite::CBC(
635 val.to_max_size()
636 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
637 ),
638 "OKTMO" => Requisite::OKTMO(
639 val.to_max_size()
640 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
641 ),
642 "PaytReason" => Requisite::PaytReason(
643 val.to_max_size()
644 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
645 ),
646 "TaxPeriod" => Requisite::TaxPeriod(
647 val.to_max_size()
648 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
649 ),
650 "DocNo" => Requisite::DocNo(
651 val.to_max_size()
652 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
653 ),
654 "DocDate" => Requisite::DocDate(
655 val.to_max_size()
656 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
657 ),
658 "TaxPayKind" => Requisite::TaxPayKind(
659 val.to_max_size()
660 .ok_or(super::Error::WrongPair(key.into(), val.into()))?,
661 ),
662 "LastName" => Requisite::LastName(val.into()),
663 "FirstName" => Requisite::FirstName(val.into()),
664 "MiddleName" => Requisite::MiddleName(val.into()),
665 "PayerAddress" => Requisite::PayerAddress(val.into()),
666 "PersonalAccount" => Requisite::PersonalAccount(val.into()),
667 "DocIdx" => Requisite::DocIdx(val.into()),
668 "PensAcc" => Requisite::PensAcc(val.into()),
669 "Flat" => Requisite::Flat(val.into()),
670 "Phone" => Requisite::Phone(val.into()),
671 "PayerIdType" => Requisite::PayerIdType(val.into()),
672 "PayerIdNum" => Requisite::PayerIdNum(val.into()),
673 "ChildFio" => Requisite::ChildFio(val.into()),
674 "BirthDate" => Requisite::BirthDate(val.into()),
675 "PaymTerm" => Requisite::PaymTerm(val.into()),
676 "PaymPeriod" => Requisite::PaymPeriod(val.into()),
677 "Category" => Requisite::Category(val.into()),
678 "ServiceName" => Requisite::ServiceName(val.into()),
679 "CounterId" => Requisite::CounterId(val.into()),
680 "CounterVal" => Requisite::CounterVal(val.into()),
681 "QuittId" => Requisite::QuittId(val.into()),
682 "QuittDate" => Requisite::QuittDate(val.into()),
683 "InstNum" => Requisite::InstNum(val.into()),
684 "ClassNum" => Requisite::ClassNum(val.into()),
685 "SpecFio" => Requisite::SpecFio(val.into()),
686 "AddAmount" => Requisite::AddAmount(val.into()),
687 "RuleId" => Requisite::RuleId(val.into()),
688 "ExecId" => Requisite::ExecId(val.into()),
689 "RegType" => Requisite::RegType(val.into()),
690 "UIN" => Requisite::UIN(val.into()),
691 "TechCode" => Requisite::TechCode(TechCode::from_str(val)?),
692 _ => Requisite::Custom((key, val).try_into()?),
693 };
694
695 Ok(requisite)
696 }
697}
698
699impl<T: CustomRequisites> Display for Requisite<T> {
700 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
701 write!(f, "{}={}", self.key(), self.value())
702 }
703}
704
705#[derive(Clone, Copy, Debug, PartialEq, Eq)]
707pub enum TechCode {
708 Mobile,
710
711 HousingAndUtilites,
713
714 Taxes,
716
717 SecurityServices,
719
720 FMS,
722
723 PFR,
725
726 LoanRepayments,
728
729 EducationalInstitutions,
731
732 InternetTV,
734
735 Emoney,
737
738 Vacation,
740
741 InvestmentInsurance,
743
744 SportHealth,
746
747 Charity,
749
750 Other,
752}
753
754impl TechCode {
755 fn as_str(&self) -> &str {
756 match self {
757 TechCode::Mobile => "01",
758 TechCode::HousingAndUtilites => "02",
759 TechCode::Taxes => "03",
760 TechCode::SecurityServices => "04",
761 TechCode::FMS => "05",
762 TechCode::PFR => "06",
763 TechCode::LoanRepayments => "07",
764 TechCode::EducationalInstitutions => "08",
765 TechCode::InternetTV => "09",
766 TechCode::Emoney => "10",
767 TechCode::Vacation => "11",
768 TechCode::InvestmentInsurance => "12",
769 TechCode::SportHealth => "13",
770 TechCode::Charity => "14",
771 TechCode::Other => "15",
772 }
773 }
774
775 fn from_str(val: &str) -> super::Result<TechCode> {
776 match val {
777 "01" => Ok(TechCode::Mobile),
778 "02" => Ok(TechCode::HousingAndUtilites),
779 "03" => Ok(TechCode::Taxes),
780 "04" => Ok(TechCode::SecurityServices),
781 "05" => Ok(TechCode::FMS),
782 "06" => Ok(TechCode::PFR),
783 "07" => Ok(TechCode::LoanRepayments),
784 "08" => Ok(TechCode::EducationalInstitutions),
785 "09" => Ok(TechCode::InternetTV),
786 "10" => Ok(TechCode::Emoney),
787 "11" => Ok(TechCode::Vacation),
788 "12" => Ok(TechCode::InvestmentInsurance),
789 "13" => Ok(TechCode::SportHealth),
790 "14" => Ok(TechCode::Charity),
791 "15" => Ok(TechCode::Other),
792 _ => Err(super::Error::UnknownTechCode(val.into())),
793 }
794 }
795}
796
797#[derive(Clone, Copy, Debug, PartialEq, Eq)]
799#[repr(u8)]
800pub enum PaymentEncoding {
801 Win1251 = b'1',
803
804 Utf8 = b'2',
806
807 Koi8R = b'3',
809}
810
811impl TryFrom<u8> for PaymentEncoding {
812 type Error = super::Error;
813
814 fn try_from(value: u8) -> super::Result<PaymentEncoding> {
815 match value {
816 b'1' => Ok(Self::Win1251),
817 b'2' => Ok(Self::Utf8),
818 b'3' => Ok(Self::Koi8R),
819 code => Err(super::Error::UnknownEncodingCode(code)),
820 }
821 }
822}
823
824impl Display for PaymentEncoding {
825 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
826 match self {
827 PaymentEncoding::Win1251 => write!(f, "Windows-1251"),
828 PaymentEncoding::Utf8 => write!(f, "Utf-8"),
829 PaymentEncoding::Koi8R => write!(f, "KOI8-R"),
830 }
831 }
832}