@@ -2,6 +2,8 @@ use core::any::TypeId;
2
2
use core:: fmt;
3
3
use core:: marker:: PhantomData ;
4
4
use core:: ops:: { Add , AddAssign , Div , DivAssign , Mul , MulAssign , Sub , SubAssign } ;
5
+ use core:: str:: FromStr ;
6
+ use core:: num:: ParseIntError ;
5
7
6
8
use approx:: { AbsDiffEq , RelativeEq , UlpsEq } ;
7
9
use float:: Float ;
@@ -953,14 +955,92 @@ where
953
955
}
954
956
}
955
957
958
+ #[ derive( Debug ) ]
959
+ pub enum FromHexError {
960
+ ParseIntError ( ParseIntError ) ,
961
+ HexFormatError ( & ' static str )
962
+ }
963
+
964
+ impl From < ParseIntError > for FromHexError {
965
+ fn from ( err : ParseIntError ) -> FromHexError {
966
+ FromHexError :: ParseIntError ( err)
967
+ }
968
+ }
969
+
970
+ impl From < & ' static str > for FromHexError {
971
+ fn from ( err : & ' static str ) -> FromHexError {
972
+ FromHexError :: HexFormatError ( err)
973
+ }
974
+ }
975
+ impl core:: fmt:: Display for FromHexError {
976
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
977
+ match & * self {
978
+ FromHexError :: ParseIntError ( e) => {
979
+ write ! ( f, "{}" , e)
980
+ }
981
+ FromHexError :: HexFormatError ( s) => {
982
+ write ! ( f, "{}, please use format '#fff', 'fff', '#ffffff' or\
983
+ 'ffffff'.", s)
984
+ }
985
+ }
986
+ }
987
+ }
988
+
989
+ #[ cfg( feature="std" ) ]
990
+ impl std:: error:: Error for FromHexError {
991
+ fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > {
992
+ match & * self {
993
+ FromHexError :: HexFormatError ( _s) => None ,
994
+ FromHexError :: ParseIntError ( e) => Some ( e) ,
995
+ }
996
+ }
997
+ }
998
+
999
+
1000
+ impl < S : RgbStandard > FromStr for Rgb < S , u8 > {
1001
+ type Err = FromHexError ;
1002
+
1003
+ // Parses a color hex code of format '#ff00bb' or '#abc' into a
1004
+ // Rgb<S, u8> instance.
1005
+ fn from_str ( hex : & str ) -> Result < Self , Self :: Err > {
1006
+ let hex_code = if hex. starts_with ( '#' ) {
1007
+ & hex[ 1 ..]
1008
+ } else {
1009
+ hex
1010
+ } ;
1011
+ match hex_code. len ( ) {
1012
+ 3 => {
1013
+ let red = u8:: from_str_radix ( & hex_code[ ..1 ] , 16 ) ?;
1014
+ let green = u8:: from_str_radix ( & hex_code[ 1 ..2 ] , 16 ) ?;
1015
+ let blue = u8:: from_str_radix ( & hex_code[ 2 ..3 ] , 16 ) ?;
1016
+ let col: Rgb < S , u8 > = Rgb :: new (
1017
+ red * 17 ,
1018
+ green * 17 ,
1019
+ blue * 17 ,
1020
+ ) ;
1021
+ Ok ( col)
1022
+ }
1023
+ 6 => {
1024
+ let red = u8:: from_str_radix ( & hex_code[ ..2 ] , 16 ) ?;
1025
+ let green = u8:: from_str_radix ( & hex_code[ 2 ..4 ] , 16 ) ?;
1026
+ let blue = u8:: from_str_radix ( & hex_code[ 4 ..6 ] , 16 ) ?;
1027
+ let col: Rgb < S , u8 > = Rgb :: new ( red, green, blue) ;
1028
+ Ok ( col)
1029
+ }
1030
+ _ => Err ( "invalid hex code format" . into ( ) ) ,
1031
+ }
1032
+ }
1033
+ }
1034
+
956
1035
#[ cfg( test) ]
957
1036
mod test {
958
1037
use super :: Rgb ;
959
1038
use encoding:: Srgb ;
1039
+ use core:: str:: FromStr ;
960
1040
961
1041
#[ test]
962
1042
fn ranges ( ) {
963
- assert_ranges ! {
1043
+ assert_ranges ! {
964
1044
Rgb <Srgb , f64 >;
965
1045
limited {
966
1046
red: 0.0 => 1.0 ,
@@ -1081,4 +1161,49 @@ mod test {
1081
1161
1082
1162
assert_eq ! ( deserialized, Rgb :: <Srgb >:: new( 0.3 , 0.8 , 0.1 ) ) ;
1083
1163
}
1164
+
1165
+ #[ test]
1166
+ fn from_str ( ) {
1167
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "#ffffff" ) ;
1168
+ assert ! ( c. is_ok( ) ) ;
1169
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 255 , 255 , 255 ) ) ;
1170
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "#gggggg" ) ;
1171
+ assert ! ( c. is_err( ) ) ;
1172
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "#fff" ) ;
1173
+ assert ! ( c. is_ok( ) ) ;
1174
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 255 , 255 , 255 ) ) ;
1175
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "#000000" ) ;
1176
+ assert ! ( c. is_ok( ) ) ;
1177
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 0 , 0 , 0 ) ) ;
1178
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "" ) ;
1179
+ assert ! ( c. is_err( ) ) ;
1180
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "#123456" ) ;
1181
+ assert ! ( c. is_ok( ) ) ;
1182
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 18 , 52 , 86 ) ) ;
1183
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "#iii" ) ;
1184
+ assert ! ( c. is_err( ) ) ;
1185
+ assert_eq ! (
1186
+ format!( "{}" , c. err( ) . unwrap( ) ) ,
1187
+ "invalid digit found in string"
1188
+ ) ;
1189
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "#08f" ) ;
1190
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 0 , 136 , 255 ) ) ;
1191
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "08f" ) ;
1192
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 0 , 136 , 255 ) ) ;
1193
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "ffffff" ) ;
1194
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 255 , 255 , 255 ) ) ;
1195
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "#12" ) ;
1196
+ assert ! ( c. is_err( ) ) ;
1197
+ assert_eq ! (
1198
+ format!( "{}" , c. err( ) . unwrap( ) ) ,
1199
+ "invalid hex code format, \
1200
+ please use format \' #fff\' , \' fff\' , \' #ffffff\' or\' ffffff\' ."
1201
+ ) ;
1202
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "da0bce" ) ;
1203
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 218 , 11 , 206 ) ) ;
1204
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "f034e6" ) ;
1205
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 240 , 52 , 230 ) ) ;
1206
+ let c = Rgb :: < Srgb , u8 > :: from_str ( "abc" ) ;
1207
+ assert_eq ! ( c. unwrap( ) , Rgb :: <Srgb , u8 >:: new( 170 , 187 , 204 ) ) ;
1208
+ }
1084
1209
}
0 commit comments