1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//! This simple tool reads potential CUSIPs from stdin, one per line, and parses them. It will panic
//! if any fail to parse. This can be used as a simple bulk test of a file of purported CUSIPs to
//! ensure there are no malformed entries present. If you have a known-good file of valid CUSIPs, it
//! can be used to validate this crate considers them valid.
//!
//! As part of the `cusip` crate's initial validation, this tool was run on a file of 1,591,249
//! unique CUSIPs produced by processing a file mapping LEIs to ISINs obtained from GLEIF. The
//! [GLEIF file](https://www.gleif.org/en/lei-data/lei-mapping/download-isin-to-lei-relationship-files)
//! is very large (the version from 2021-02-09 was about 170MB). Here are a few example records for
//! US ISINS:
//!
//! ```sh
//! grep ',US' ISIN_LEI_20210209.csv | head
//! S6XOOCT0IEG5ABCC6L87,US3137A3KN83
//! 254900EDYO1UYWLWP146,US12613N2027
//! 549300DRQQI75D2JP341,US05531GQN42
//! S6XOOCT0IEG5ABCC6L87,US31394GAX16
//! S6XOOCT0IEG5ABCC6L87,US3137ASGH19
//! G5GSEF7VJP5I7OUK5573,US06741RAP64
//! 549300LR1ZETOWYE9Z89,US084601MZ36
//! 8I5DZWZKVSZI1NUHU748,US46636JTK96
//! ANGGYXNX0JLX3X63JN86,US22546ESF24
//! 784F5XWPLTWKTBV3E584,US38143USC61
//! ```
//!
//! You can use a command like this to subset just the US ISINs and convert them to putative CUSIPs:
//!
//! ```sh
//! grep ',US' ISIN_LEI_20210209.csv \
//! | sed -e 's/^.*,US//' \
//! | sed -e 's/.$//' \
//! | sort | uniq | gzip -9 \
//! > cusips-us.txt.gz
//! ```
//!
//! This file was still about 4.2MB for the version tested.
//!
//! Having produced the file, it is now possible to run it through this tool. From the source
//! directory of this crate, you can run:
//!
//! ```sh
//! gzcat cusips-us.txt.gz | cargo run cusip-tool
//! ```
//!
//! And, output will be something like this:
//!
//! ```text
//! Read 1591249 values; 1591249 were valid CUSIPs and 0 were not.
//! ```
//!
//! If no bad values were found, the tool will exit with zero status, else non-zero.
//!
//! ## Fix mode
//!
//! If you run with argument `--fix`, then any input CUSIPs that are only wrong due to incorrect
//! _Check Digit_ will be fixed. In this mode, every good and every fixable input CUSIP is printed
//! to standard output.
use CUSIP;
use env;
use io;
use *;
use from_utf8_unchecked;