(v reflect.Value, expr *unstable.Node, value *unstable.Node)
| 1881 | } |
| 1882 | |
| 1883 | func (d *decoder) assignArray(v reflect.Value, expr *unstable.Node, value *unstable.Node) (reflect.Value, error) { |
| 1884 | // Count the elements to allocate the target in one go. |
| 1885 | count := 0 |
| 1886 | cit := value.Children() |
| 1887 | for cit.Next() { |
| 1888 | if cit.Node().Kind != unstable.Comment { |
| 1889 | count++ |
| 1890 | } |
| 1891 | } |
| 1892 | |
| 1893 | switch v.Kind() { |
| 1894 | case reflect.Slice: |
| 1895 | // Allocate the backing array once at its final length and assign each |
| 1896 | // element in place. This avoids a reflect.New allocation per element |
| 1897 | // and the repeated growth checks of reflect.Append. |
| 1898 | slice := reflect.MakeSlice(v.Type(), count, count) |
| 1899 | i := 0 |
| 1900 | it := value.Children() |
| 1901 | for it.Next() { |
| 1902 | n := it.Node() |
| 1903 | if n.Kind == unstable.Comment { |
| 1904 | continue |
| 1905 | } |
| 1906 | elem := slice.Index(i) |
| 1907 | nv, err := d.assignValue(elem, nil, n) |
| 1908 | if err != nil { |
| 1909 | return reflect.Value{}, err |
| 1910 | } |
| 1911 | if nv.IsValid() { |
| 1912 | elem.Set(nv) |
| 1913 | } |
| 1914 | i++ |
| 1915 | } |
| 1916 | return slice, nil |
| 1917 | case reflect.Array: |
| 1918 | it := value.Children() |
| 1919 | i := 0 |
| 1920 | for it.Next() { |
| 1921 | n := it.Node() |
| 1922 | if n.Kind == unstable.Comment { |
| 1923 | continue |
| 1924 | } |
| 1925 | if i >= v.Len() { |
| 1926 | // Extra elements are dropped when the target array is too |
| 1927 | // small. |
| 1928 | break |
| 1929 | } |
| 1930 | elem := v.Index(i) |
| 1931 | nv, err := d.assignValue(elem, nil, n) |
| 1932 | if err != nil { |
| 1933 | return reflect.Value{}, err |
| 1934 | } |
| 1935 | elem.Set(nv) |
| 1936 | i++ |
| 1937 | } |
| 1938 | return v, nil |
| 1939 | case reflect.Interface: |
| 1940 | // Build the []interface{} natively: each element is decoded straight |
no test coverage detected