@@ -428,8 +428,10 @@ impl WrongType {
428428///
429429/// # Arrays
430430///
431- /// `FromSql` is implemented for `Vec<T>` where `T` implements `FromSql`, and
432- /// corresponds to one-dimensional Postgres arrays.
431+ /// `FromSql` is implemented for `Vec<T>` and `[T; N]` where `T` implements
432+ /// `FromSql`, and corresponds to one-dimensional Postgres arrays. **Note:**
433+ /// the impl for arrays only exist when the Cargo feature `array-impls` is
434+ /// enabled.
433435pub trait FromSql < ' a > : Sized {
434436 /// Creates a new value of this type from a buffer of data of the specified
435437 /// Postgres `Type` in its binary format.
@@ -513,6 +515,47 @@ impl<'a, T: FromSql<'a>> FromSql<'a> for Vec<T> {
513515 }
514516}
515517
518+ #[ cfg( feature = "array-impls" ) ]
519+ impl < ' a , T : FromSql < ' a > , const N : usize > FromSql < ' a > for [ T ; N ] {
520+ fn from_sql ( ty : & Type , raw : & ' a [ u8 ] ) -> Result < Self , Box < dyn Error + Sync + Send > > {
521+ let member_type = match * ty. kind ( ) {
522+ Kind :: Array ( ref member) => member,
523+ _ => panic ! ( "expected array type" ) ,
524+ } ;
525+
526+ let array = types:: array_from_sql ( raw) ?;
527+ if array. dimensions ( ) . count ( ) ? > 1 {
528+ return Err ( "array contains too many dimensions" . into ( ) ) ;
529+ }
530+
531+ let mut values = array. values ( ) ;
532+ let out = array_init:: try_array_init ( |i| {
533+ let v = values
534+ . next ( ) ?
535+ . ok_or_else ( || -> Box < dyn Error + Sync + Send > {
536+ format ! ( "too few elements in array (expected {}, got {})" , N , i) . into ( )
537+ } ) ?;
538+ T :: from_sql_nullable ( member_type, v)
539+ } ) ?;
540+ if values. next ( ) ?. is_some ( ) {
541+ return Err ( format ! (
542+ "excess elements in array (expected {}, got more than that)" ,
543+ N ,
544+ )
545+ . into ( ) ) ;
546+ }
547+
548+ Ok ( out)
549+ }
550+
551+ fn accepts ( ty : & Type ) -> bool {
552+ match * ty. kind ( ) {
553+ Kind :: Array ( ref inner) => T :: accepts ( inner) ,
554+ _ => false ,
555+ }
556+ }
557+ }
558+
516559impl < ' a > FromSql < ' a > for Vec < u8 > {
517560 fn from_sql ( _: & Type , raw : & ' a [ u8 ] ) -> Result < Vec < u8 > , Box < dyn Error + Sync + Send > > {
518561 Ok ( types:: bytea_from_sql ( raw) . to_owned ( ) )
@@ -691,8 +734,10 @@ pub enum IsNull {
691734///
692735/// # Arrays
693736///
694- /// `ToSql` is implemented for `Vec<T>` and `&[T]` where `T` implements `ToSql`,
695- /// and corresponds to one-dimensional Postgres arrays with an index offset of 1.
737+ /// `ToSql` is implemented for `Vec<T>`, `&[T]` and `[T; N]` where `T`
738+ /// implements `ToSql`, and corresponds to one-dimensional Postgres arrays with
739+ /// an index offset of 1. **Note:** the impl for arrays only exist when the
740+ /// Cargo feature `array-impls` is enabled.
696741pub trait ToSql : fmt:: Debug {
697742 /// Converts the value of `self` into the binary format of the specified
698743 /// Postgres `Type`, appending it to `out`.
@@ -808,6 +853,19 @@ impl<'a> ToSql for &'a [u8] {
808853 to_sql_checked ! ( ) ;
809854}
810855
856+ #[ cfg( feature = "array-impls" ) ]
857+ impl < T : ToSql , const N : usize > ToSql for [ T ; N ] {
858+ fn to_sql ( & self , ty : & Type , w : & mut BytesMut ) -> Result < IsNull , Box < dyn Error + Sync + Send > > {
859+ <& [ T ] as ToSql >:: to_sql ( & & self [ ..] , ty, w)
860+ }
861+
862+ fn accepts ( ty : & Type ) -> bool {
863+ <& [ T ] as ToSql >:: accepts ( ty)
864+ }
865+
866+ to_sql_checked ! ( ) ;
867+ }
868+
811869impl < T : ToSql > ToSql for Vec < T > {
812870 fn to_sql ( & self , ty : & Type , w : & mut BytesMut ) -> Result < IsNull , Box < dyn Error + Sync + Send > > {
813871 <& [ T ] as ToSql >:: to_sql ( & & * * self , ty, w)
0 commit comments