Backend: Remove Go vendor folder (#23796)

This commit is contained in:
Kyle Brandt
2020-04-23 13:23:51 -04:00
committed by GitHub
parent e0dbd87a5a
commit 6d500e31b9
2609 changed files with 3 additions and 1246445 deletions

1
.gitignore vendored
View File

@@ -14,6 +14,7 @@ awsconfig
/e2e/tmp
.yarnrc
.yarn/
vendor/
# Enterprise emails
/emails/templates/enterprise_*

View File

@@ -20,8 +20,6 @@ Upgrading Go or Node.js requires making changes in many different files. See bel
The Grafana project uses [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) to manage dependencies on external packages. This requires a working Go environment with version 1.11 or greater installed.
All dependencies are vendored in the `vendor/` directory.
_Note:_ Since most developers of Grafana still use the `GOPATH` we need to specify `GO111MODULE=on` to make `go mod` and `got get` work as intended. If you have setup Grafana outside of the `GOPATH` on your machine you can skip `GO111MODULE=on` when running the commands below.
To add or update a new dependency, use the `go get` command:
@@ -35,16 +33,14 @@ GO111MODULE=on go get example.com/some/module/pkg
GO111MODULE=on go get example.com/some/module/pkg@vX.Y.Z
```
Tidy up the `go.mod` and `go.sum` files and copy the new/updated dependency to the `vendor/` directory:
Tidy up the `go.mod` and `go.sum` files:
```bash
# The GO111MODULE variable can be omitted when the code isn't located in GOPATH.
GO111MODULE=on go mod tidy
GO111MODULE=on go mod vendor
```
You have to commit the changes to `go.mod`, `go.sum` and the `vendor/` directory before submitting the pull request.
You have to commit the changes to `go.mod` and `go.sum` before submitting the pull request.
## Node.js dependencies

View File

@@ -51,7 +51,6 @@ var (
skipRpmGen bool = false
skipDebGen bool = false
printGenVersion bool = false
modVendor bool = true
)
func main() {
@@ -69,7 +68,6 @@ func main() {
flag.BoolVar(&cgo, "cgo-enabled", cgo, "Enable cgo")
flag.StringVar(&pkgArch, "pkg-arch", "", "PKG ARCH")
flag.BoolVar(&race, "race", race, "Use race detector")
flag.BoolVar(&modVendor, "modVendor", modVendor, "Go modules use vendor folder")
flag.BoolVar(&includeBuildId, "includeBuildId", includeBuildId, "IncludeBuildId in package name")
flag.BoolVar(&enterprise, "enterprise", enterprise, "Build enterprise version of Grafana")
flag.StringVar(&buildIdRaw, "buildId", "0", "Build ID from CI system")
@@ -387,7 +385,6 @@ func createPackage(options linuxPackageOptions) {
if enterprise {
description += " Enterprise"
}
args = append(args, "--vendor", description)
if !enterprise {
args = append(args, "--license", "\"Apache 2.0\"")
@@ -504,9 +501,6 @@ func build(binaryName, pkg string, tags []string) {
if race {
args = append(args, "-race")
}
if modVendor {
args = append(args, "-mod=vendor")
}
args = append(args, "-o", binary)
args = append(args, pkg)

202
vendor/cloud.google.com/go/LICENSE generated vendored
View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,277 +0,0 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package civil implements types for civil time, a time-zone-independent
// representation of time that follows the rules of the proleptic
// Gregorian calendar with exactly 24-hour days, 60-minute hours, and 60-second
// minutes.
//
// Because they lack location information, these types do not represent unique
// moments or intervals of time. Use time.Time for that purpose.
package civil
import (
"fmt"
"time"
)
// A Date represents a date (year, month, day).
//
// This type does not include location information, and therefore does not
// describe a unique 24-hour timespan.
type Date struct {
Year int // Year (e.g., 2014).
Month time.Month // Month of the year (January = 1, ...).
Day int // Day of the month, starting at 1.
}
// DateOf returns the Date in which a time occurs in that time's location.
func DateOf(t time.Time) Date {
var d Date
d.Year, d.Month, d.Day = t.Date()
return d
}
// ParseDate parses a string in RFC3339 full-date format and returns the date value it represents.
func ParseDate(s string) (Date, error) {
t, err := time.Parse("2006-01-02", s)
if err != nil {
return Date{}, err
}
return DateOf(t), nil
}
// String returns the date in RFC3339 full-date format.
func (d Date) String() string {
return fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day)
}
// IsValid reports whether the date is valid.
func (d Date) IsValid() bool {
return DateOf(d.In(time.UTC)) == d
}
// In returns the time corresponding to time 00:00:00 of the date in the location.
//
// In is always consistent with time.Date, even when time.Date returns a time
// on a different day. For example, if loc is America/Indiana/Vincennes, then both
// time.Date(1955, time.May, 1, 0, 0, 0, 0, loc)
// and
// civil.Date{Year: 1955, Month: time.May, Day: 1}.In(loc)
// return 23:00:00 on April 30, 1955.
//
// In panics if loc is nil.
func (d Date) In(loc *time.Location) time.Time {
return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, loc)
}
// AddDays returns the date that is n days in the future.
// n can also be negative to go into the past.
func (d Date) AddDays(n int) Date {
return DateOf(d.In(time.UTC).AddDate(0, 0, n))
}
// DaysSince returns the signed number of days between the date and s, not including the end day.
// This is the inverse operation to AddDays.
func (d Date) DaysSince(s Date) (days int) {
// We convert to Unix time so we do not have to worry about leap seconds:
// Unix time increases by exactly 86400 seconds per day.
deltaUnix := d.In(time.UTC).Unix() - s.In(time.UTC).Unix()
return int(deltaUnix / 86400)
}
// Before reports whether d1 occurs before d2.
func (d1 Date) Before(d2 Date) bool {
if d1.Year != d2.Year {
return d1.Year < d2.Year
}
if d1.Month != d2.Month {
return d1.Month < d2.Month
}
return d1.Day < d2.Day
}
// After reports whether d1 occurs after d2.
func (d1 Date) After(d2 Date) bool {
return d2.Before(d1)
}
// MarshalText implements the encoding.TextMarshaler interface.
// The output is the result of d.String().
func (d Date) MarshalText() ([]byte, error) {
return []byte(d.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// The date is expected to be a string in a format accepted by ParseDate.
func (d *Date) UnmarshalText(data []byte) error {
var err error
*d, err = ParseDate(string(data))
return err
}
// A Time represents a time with nanosecond precision.
//
// This type does not include location information, and therefore does not
// describe a unique moment in time.
//
// This type exists to represent the TIME type in storage-based APIs like BigQuery.
// Most operations on Times are unlikely to be meaningful. Prefer the DateTime type.
type Time struct {
Hour int // The hour of the day in 24-hour format; range [0-23]
Minute int // The minute of the hour; range [0-59]
Second int // The second of the minute; range [0-59]
Nanosecond int // The nanosecond of the second; range [0-999999999]
}
// TimeOf returns the Time representing the time of day in which a time occurs
// in that time's location. It ignores the date.
func TimeOf(t time.Time) Time {
var tm Time
tm.Hour, tm.Minute, tm.Second = t.Clock()
tm.Nanosecond = t.Nanosecond()
return tm
}
// ParseTime parses a string and returns the time value it represents.
// ParseTime accepts an extended form of the RFC3339 partial-time format. After
// the HH:MM:SS part of the string, an optional fractional part may appear,
// consisting of a decimal point followed by one to nine decimal digits.
// (RFC3339 admits only one digit after the decimal point).
func ParseTime(s string) (Time, error) {
t, err := time.Parse("15:04:05.999999999", s)
if err != nil {
return Time{}, err
}
return TimeOf(t), nil
}
// String returns the date in the format described in ParseTime. If Nanoseconds
// is zero, no fractional part will be generated. Otherwise, the result will
// end with a fractional part consisting of a decimal point and nine digits.
func (t Time) String() string {
s := fmt.Sprintf("%02d:%02d:%02d", t.Hour, t.Minute, t.Second)
if t.Nanosecond == 0 {
return s
}
return s + fmt.Sprintf(".%09d", t.Nanosecond)
}
// IsValid reports whether the time is valid.
func (t Time) IsValid() bool {
// Construct a non-zero time.
tm := time.Date(2, 2, 2, t.Hour, t.Minute, t.Second, t.Nanosecond, time.UTC)
return TimeOf(tm) == t
}
// MarshalText implements the encoding.TextMarshaler interface.
// The output is the result of t.String().
func (t Time) MarshalText() ([]byte, error) {
return []byte(t.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// The time is expected to be a string in a format accepted by ParseTime.
func (t *Time) UnmarshalText(data []byte) error {
var err error
*t, err = ParseTime(string(data))
return err
}
// A DateTime represents a date and time.
//
// This type does not include location information, and therefore does not
// describe a unique moment in time.
type DateTime struct {
Date Date
Time Time
}
// Note: We deliberately do not embed Date into DateTime, to avoid promoting AddDays and Sub.
// DateTimeOf returns the DateTime in which a time occurs in that time's location.
func DateTimeOf(t time.Time) DateTime {
return DateTime{
Date: DateOf(t),
Time: TimeOf(t),
}
}
// ParseDateTime parses a string and returns the DateTime it represents.
// ParseDateTime accepts a variant of the RFC3339 date-time format that omits
// the time offset but includes an optional fractional time, as described in
// ParseTime. Informally, the accepted format is
// YYYY-MM-DDTHH:MM:SS[.FFFFFFFFF]
// where the 'T' may be a lower-case 't'.
func ParseDateTime(s string) (DateTime, error) {
t, err := time.Parse("2006-01-02T15:04:05.999999999", s)
if err != nil {
t, err = time.Parse("2006-01-02t15:04:05.999999999", s)
if err != nil {
return DateTime{}, err
}
}
return DateTimeOf(t), nil
}
// String returns the date in the format described in ParseDate.
func (dt DateTime) String() string {
return dt.Date.String() + "T" + dt.Time.String()
}
// IsValid reports whether the datetime is valid.
func (dt DateTime) IsValid() bool {
return dt.Date.IsValid() && dt.Time.IsValid()
}
// In returns the time corresponding to the DateTime in the given location.
//
// If the time is missing or ambigous at the location, In returns the same
// result as time.Date. For example, if loc is America/Indiana/Vincennes, then
// both
// time.Date(1955, time.May, 1, 0, 30, 0, 0, loc)
// and
// civil.DateTime{
// civil.Date{Year: 1955, Month: time.May, Day: 1}},
// civil.Time{Minute: 30}}.In(loc)
// return 23:30:00 on April 30, 1955.
//
// In panics if loc is nil.
func (dt DateTime) In(loc *time.Location) time.Time {
return time.Date(dt.Date.Year, dt.Date.Month, dt.Date.Day, dt.Time.Hour, dt.Time.Minute, dt.Time.Second, dt.Time.Nanosecond, loc)
}
// Before reports whether dt1 occurs before dt2.
func (dt1 DateTime) Before(dt2 DateTime) bool {
return dt1.In(time.UTC).Before(dt2.In(time.UTC))
}
// After reports whether dt1 occurs after dt2.
func (dt1 DateTime) After(dt2 DateTime) bool {
return dt2.Before(dt1)
}
// MarshalText implements the encoding.TextMarshaler interface.
// The output is the result of dt.String().
func (dt DateTime) MarshalText() ([]byte, error) {
return []byte(dt.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// The datetime is expected to be a string in a format accepted by ParseDateTime
func (dt *DateTime) UnmarshalText(data []byte) error {
var err error
*dt, err = ParseDateTime(string(data))
return err
}

View File

@@ -1,513 +0,0 @@
// Copyright 2014 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package metadata provides access to Google Compute Engine (GCE)
// metadata and API service accounts.
//
// This package is a wrapper around the GCE metadata service,
// as documented at https://developers.google.com/compute/docs/metadata.
package metadata // import "cloud.google.com/go/compute/metadata"
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"runtime"
"strings"
"sync"
"time"
)
const (
// metadataIP is the documented metadata server IP address.
metadataIP = "169.254.169.254"
// metadataHostEnv is the environment variable specifying the
// GCE metadata hostname. If empty, the default value of
// metadataIP ("169.254.169.254") is used instead.
// This is variable name is not defined by any spec, as far as
// I know; it was made up for the Go package.
metadataHostEnv = "GCE_METADATA_HOST"
userAgent = "gcloud-golang/0.1"
)
type cachedValue struct {
k string
trim bool
mu sync.Mutex
v string
}
var (
projID = &cachedValue{k: "project/project-id", trim: true}
projNum = &cachedValue{k: "project/numeric-project-id", trim: true}
instID = &cachedValue{k: "instance/id", trim: true}
)
var (
defaultClient = &Client{hc: &http.Client{
Transport: &http.Transport{
Dial: (&net.Dialer{
Timeout: 2 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
ResponseHeaderTimeout: 2 * time.Second,
},
}}
subscribeClient = &Client{hc: &http.Client{
Transport: &http.Transport{
Dial: (&net.Dialer{
Timeout: 2 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
},
}}
)
// NotDefinedError is returned when requested metadata is not defined.
//
// The underlying string is the suffix after "/computeMetadata/v1/".
//
// This error is not returned if the value is defined to be the empty
// string.
type NotDefinedError string
func (suffix NotDefinedError) Error() string {
return fmt.Sprintf("metadata: GCE metadata %q not defined", string(suffix))
}
func (c *cachedValue) get(cl *Client) (v string, err error) {
defer c.mu.Unlock()
c.mu.Lock()
if c.v != "" {
return c.v, nil
}
if c.trim {
v, err = cl.getTrimmed(c.k)
} else {
v, err = cl.Get(c.k)
}
if err == nil {
c.v = v
}
return
}
var (
onGCEOnce sync.Once
onGCE bool
)
// OnGCE reports whether this process is running on Google Compute Engine.
func OnGCE() bool {
onGCEOnce.Do(initOnGCE)
return onGCE
}
func initOnGCE() {
onGCE = testOnGCE()
}
func testOnGCE() bool {
// The user explicitly said they're on GCE, so trust them.
if os.Getenv(metadataHostEnv) != "" {
return true
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
resc := make(chan bool, 2)
// Try two strategies in parallel.
// See https://github.com/googleapis/google-cloud-go/issues/194
go func() {
req, _ := http.NewRequest("GET", "http://"+metadataIP, nil)
req.Header.Set("User-Agent", userAgent)
res, err := defaultClient.hc.Do(req.WithContext(ctx))
if err != nil {
resc <- false
return
}
defer res.Body.Close()
resc <- res.Header.Get("Metadata-Flavor") == "Google"
}()
go func() {
addrs, err := net.LookupHost("metadata.google.internal")
if err != nil || len(addrs) == 0 {
resc <- false
return
}
resc <- strsContains(addrs, metadataIP)
}()
tryHarder := systemInfoSuggestsGCE()
if tryHarder {
res := <-resc
if res {
// The first strategy succeeded, so let's use it.
return true
}
// Wait for either the DNS or metadata server probe to
// contradict the other one and say we are running on
// GCE. Give it a lot of time to do so, since the system
// info already suggests we're running on a GCE BIOS.
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()
select {
case res = <-resc:
return res
case <-timer.C:
// Too slow. Who knows what this system is.
return false
}
}
// There's no hint from the system info that we're running on
// GCE, so use the first probe's result as truth, whether it's
// true or false. The goal here is to optimize for speed for
// users who are NOT running on GCE. We can't assume that
// either a DNS lookup or an HTTP request to a blackholed IP
// address is fast. Worst case this should return when the
// metaClient's Transport.ResponseHeaderTimeout or
// Transport.Dial.Timeout fires (in two seconds).
return <-resc
}
// systemInfoSuggestsGCE reports whether the local system (without
// doing network requests) suggests that we're running on GCE. If this
// returns true, testOnGCE tries a bit harder to reach its metadata
// server.
func systemInfoSuggestsGCE() bool {
if runtime.GOOS != "linux" {
// We don't have any non-Linux clues available, at least yet.
return false
}
slurp, _ := ioutil.ReadFile("/sys/class/dmi/id/product_name")
name := strings.TrimSpace(string(slurp))
return name == "Google" || name == "Google Compute Engine"
}
// Subscribe calls Client.Subscribe on a client designed for subscribing (one with no
// ResponseHeaderTimeout).
func Subscribe(suffix string, fn func(v string, ok bool) error) error {
return subscribeClient.Subscribe(suffix, fn)
}
// Get calls Client.Get on the default client.
func Get(suffix string) (string, error) { return defaultClient.Get(suffix) }
// ProjectID returns the current instance's project ID string.
func ProjectID() (string, error) { return defaultClient.ProjectID() }
// NumericProjectID returns the current instance's numeric project ID.
func NumericProjectID() (string, error) { return defaultClient.NumericProjectID() }
// InternalIP returns the instance's primary internal IP address.
func InternalIP() (string, error) { return defaultClient.InternalIP() }
// ExternalIP returns the instance's primary external (public) IP address.
func ExternalIP() (string, error) { return defaultClient.ExternalIP() }
// Hostname returns the instance's hostname. This will be of the form
// "<instanceID>.c.<projID>.internal".
func Hostname() (string, error) { return defaultClient.Hostname() }
// InstanceTags returns the list of user-defined instance tags,
// assigned when initially creating a GCE instance.
func InstanceTags() ([]string, error) { return defaultClient.InstanceTags() }
// InstanceID returns the current VM's numeric instance ID.
func InstanceID() (string, error) { return defaultClient.InstanceID() }
// InstanceName returns the current VM's instance ID string.
func InstanceName() (string, error) { return defaultClient.InstanceName() }
// Zone returns the current VM's zone, such as "us-central1-b".
func Zone() (string, error) { return defaultClient.Zone() }
// InstanceAttributes calls Client.InstanceAttributes on the default client.
func InstanceAttributes() ([]string, error) { return defaultClient.InstanceAttributes() }
// ProjectAttributes calls Client.ProjectAttributes on the default client.
func ProjectAttributes() ([]string, error) { return defaultClient.ProjectAttributes() }
// InstanceAttributeValue calls Client.InstanceAttributeValue on the default client.
func InstanceAttributeValue(attr string) (string, error) {
return defaultClient.InstanceAttributeValue(attr)
}
// ProjectAttributeValue calls Client.ProjectAttributeValue on the default client.
func ProjectAttributeValue(attr string) (string, error) {
return defaultClient.ProjectAttributeValue(attr)
}
// Scopes calls Client.Scopes on the default client.
func Scopes(serviceAccount string) ([]string, error) { return defaultClient.Scopes(serviceAccount) }
func strsContains(ss []string, s string) bool {
for _, v := range ss {
if v == s {
return true
}
}
return false
}
// A Client provides metadata.
type Client struct {
hc *http.Client
}
// NewClient returns a Client that can be used to fetch metadata. All HTTP requests
// will use the given http.Client instead of the default client.
func NewClient(c *http.Client) *Client {
return &Client{hc: c}
}
// getETag returns a value from the metadata service as well as the associated ETag.
// This func is otherwise equivalent to Get.
func (c *Client) getETag(suffix string) (value, etag string, err error) {
// Using a fixed IP makes it very difficult to spoof the metadata service in
// a container, which is an important use-case for local testing of cloud
// deployments. To enable spoofing of the metadata service, the environment
// variable GCE_METADATA_HOST is first inspected to decide where metadata
// requests shall go.
host := os.Getenv(metadataHostEnv)
if host == "" {
// Using 169.254.169.254 instead of "metadata" here because Go
// binaries built with the "netgo" tag and without cgo won't
// know the search suffix for "metadata" is
// ".google.internal", and this IP address is documented as
// being stable anyway.
host = metadataIP
}
u := "http://" + host + "/computeMetadata/v1/" + suffix
req, _ := http.NewRequest("GET", u, nil)
req.Header.Set("Metadata-Flavor", "Google")
req.Header.Set("User-Agent", userAgent)
res, err := c.hc.Do(req)
if err != nil {
return "", "", err
}
defer res.Body.Close()
if res.StatusCode == http.StatusNotFound {
return "", "", NotDefinedError(suffix)
}
all, err := ioutil.ReadAll(res.Body)
if err != nil {
return "", "", err
}
if res.StatusCode != 200 {
return "", "", &Error{Code: res.StatusCode, Message: string(all)}
}
return string(all), res.Header.Get("Etag"), nil
}
// Get returns a value from the metadata service.
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
//
// If the GCE_METADATA_HOST environment variable is not defined, a default of
// 169.254.169.254 will be used instead.
//
// If the requested metadata is not defined, the returned error will
// be of type NotDefinedError.
func (c *Client) Get(suffix string) (string, error) {
val, _, err := c.getETag(suffix)
return val, err
}
func (c *Client) getTrimmed(suffix string) (s string, err error) {
s, err = c.Get(suffix)
s = strings.TrimSpace(s)
return
}
func (c *Client) lines(suffix string) ([]string, error) {
j, err := c.Get(suffix)
if err != nil {
return nil, err
}
s := strings.Split(strings.TrimSpace(j), "\n")
for i := range s {
s[i] = strings.TrimSpace(s[i])
}
return s, nil
}
// ProjectID returns the current instance's project ID string.
func (c *Client) ProjectID() (string, error) { return projID.get(c) }
// NumericProjectID returns the current instance's numeric project ID.
func (c *Client) NumericProjectID() (string, error) { return projNum.get(c) }
// InstanceID returns the current VM's numeric instance ID.
func (c *Client) InstanceID() (string, error) { return instID.get(c) }
// InternalIP returns the instance's primary internal IP address.
func (c *Client) InternalIP() (string, error) {
return c.getTrimmed("instance/network-interfaces/0/ip")
}
// ExternalIP returns the instance's primary external (public) IP address.
func (c *Client) ExternalIP() (string, error) {
return c.getTrimmed("instance/network-interfaces/0/access-configs/0/external-ip")
}
// Hostname returns the instance's hostname. This will be of the form
// "<instanceID>.c.<projID>.internal".
func (c *Client) Hostname() (string, error) {
return c.getTrimmed("instance/hostname")
}
// InstanceTags returns the list of user-defined instance tags,
// assigned when initially creating a GCE instance.
func (c *Client) InstanceTags() ([]string, error) {
var s []string
j, err := c.Get("instance/tags")
if err != nil {
return nil, err
}
if err := json.NewDecoder(strings.NewReader(j)).Decode(&s); err != nil {
return nil, err
}
return s, nil
}
// InstanceName returns the current VM's instance ID string.
func (c *Client) InstanceName() (string, error) {
host, err := c.Hostname()
if err != nil {
return "", err
}
return strings.Split(host, ".")[0], nil
}
// Zone returns the current VM's zone, such as "us-central1-b".
func (c *Client) Zone() (string, error) {
zone, err := c.getTrimmed("instance/zone")
// zone is of the form "projects/<projNum>/zones/<zoneName>".
if err != nil {
return "", err
}
return zone[strings.LastIndex(zone, "/")+1:], nil
}
// InstanceAttributes returns the list of user-defined attributes,
// assigned when initially creating a GCE VM instance. The value of an
// attribute can be obtained with InstanceAttributeValue.
func (c *Client) InstanceAttributes() ([]string, error) { return c.lines("instance/attributes/") }
// ProjectAttributes returns the list of user-defined attributes
// applying to the project as a whole, not just this VM. The value of
// an attribute can be obtained with ProjectAttributeValue.
func (c *Client) ProjectAttributes() ([]string, error) { return c.lines("project/attributes/") }
// InstanceAttributeValue returns the value of the provided VM
// instance attribute.
//
// If the requested attribute is not defined, the returned error will
// be of type NotDefinedError.
//
// InstanceAttributeValue may return ("", nil) if the attribute was
// defined to be the empty string.
func (c *Client) InstanceAttributeValue(attr string) (string, error) {
return c.Get("instance/attributes/" + attr)
}
// ProjectAttributeValue returns the value of the provided
// project attribute.
//
// If the requested attribute is not defined, the returned error will
// be of type NotDefinedError.
//
// ProjectAttributeValue may return ("", nil) if the attribute was
// defined to be the empty string.
func (c *Client) ProjectAttributeValue(attr string) (string, error) {
return c.Get("project/attributes/" + attr)
}
// Scopes returns the service account scopes for the given account.
// The account may be empty or the string "default" to use the instance's
// main account.
func (c *Client) Scopes(serviceAccount string) ([]string, error) {
if serviceAccount == "" {
serviceAccount = "default"
}
return c.lines("instance/service-accounts/" + serviceAccount + "/scopes")
}
// Subscribe subscribes to a value from the metadata service.
// The suffix is appended to "http://${GCE_METADATA_HOST}/computeMetadata/v1/".
// The suffix may contain query parameters.
//
// Subscribe calls fn with the latest metadata value indicated by the provided
// suffix. If the metadata value is deleted, fn is called with the empty string
// and ok false. Subscribe blocks until fn returns a non-nil error or the value
// is deleted. Subscribe returns the error value returned from the last call to
// fn, which may be nil when ok == false.
func (c *Client) Subscribe(suffix string, fn func(v string, ok bool) error) error {
const failedSubscribeSleep = time.Second * 5
// First check to see if the metadata value exists at all.
val, lastETag, err := c.getETag(suffix)
if err != nil {
return err
}
if err := fn(val, true); err != nil {
return err
}
ok := true
if strings.ContainsRune(suffix, '?') {
suffix += "&wait_for_change=true&last_etag="
} else {
suffix += "?wait_for_change=true&last_etag="
}
for {
val, etag, err := c.getETag(suffix + url.QueryEscape(lastETag))
if err != nil {
if _, deleted := err.(NotDefinedError); !deleted {
time.Sleep(failedSubscribeSleep)
continue // Retry on other errors.
}
ok = false
}
lastETag = etag
if err := fn(val, ok); err != nil || !ok {
return err
}
}
}
// Error contains an error response from the server.
type Error struct {
// Code is the HTTP response status code.
Code int
// Message is the server response message.
Message string
}
func (e *Error) Error() string {
return fmt.Sprintf("compute: Received %d `%s`", e.Code, e.Message)
}

View File

@@ -1,5 +0,0 @@
TAGS
tags
.*.swp
tomlcheck/tomlcheck
toml.test

View File

@@ -1,3 +0,0 @@
Compatible with TOML version
[v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md)

View File

@@ -1,21 +0,0 @@
The MIT License (MIT)
Copyright (c) 2013 TOML authors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -1,19 +0,0 @@
install:
go install ./...
test: install
go test -v
toml-test toml-test-decoder
toml-test -encoder toml-test-encoder
fmt:
gofmt -w *.go */*.go
colcheck *.go */*.go
tags:
find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS
push:
git push origin master
git push github master

View File

@@ -1,218 +0,0 @@
## TOML parser and encoder for Go with reflection
TOML stands for Tom's Obvious, Minimal Language. This Go package provides a
reflection interface similar to Go's standard library `json` and `xml`
packages. This package also supports the `encoding.TextUnmarshaler` and
`encoding.TextMarshaler` interfaces so that you can define custom data
representations. (There is an example of this below.)
Spec: https://github.com/toml-lang/toml
Compatible with TOML version
[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md)
Documentation: https://godoc.org/github.com/BurntSushi/toml
Installation:
```bash
go get github.com/BurntSushi/toml
```
Try the toml validator:
```bash
go get github.com/BurntSushi/toml/cmd/tomlv
tomlv some-toml-file.toml
```
[![Build Status](https://travis-ci.org/BurntSushi/toml.svg?branch=master)](https://travis-ci.org/BurntSushi/toml) [![GoDoc](https://godoc.org/github.com/BurntSushi/toml?status.svg)](https://godoc.org/github.com/BurntSushi/toml)
### Testing
This package passes all tests in
[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder
and the encoder.
### Examples
This package works similarly to how the Go standard library handles `XML`
and `JSON`. Namely, data is loaded into Go values via reflection.
For the simplest example, consider some TOML file as just a list of keys
and values:
```toml
Age = 25
Cats = [ "Cauchy", "Plato" ]
Pi = 3.14
Perfection = [ 6, 28, 496, 8128 ]
DOB = 1987-07-05T05:45:00Z
```
Which could be defined in Go as:
```go
type Config struct {
Age int
Cats []string
Pi float64
Perfection []int
DOB time.Time // requires `import time`
}
```
And then decoded with:
```go
var conf Config
if _, err := toml.Decode(tomlData, &conf); err != nil {
// handle error
}
```
You can also use struct tags if your struct field name doesn't map to a TOML
key value directly:
```toml
some_key_NAME = "wat"
```
```go
type TOML struct {
ObscureKey string `toml:"some_key_NAME"`
}
```
### Using the `encoding.TextUnmarshaler` interface
Here's an example that automatically parses duration strings into
`time.Duration` values:
```toml
[[song]]
name = "Thunder Road"
duration = "4m49s"
[[song]]
name = "Stairway to Heaven"
duration = "8m03s"
```
Which can be decoded with:
```go
type song struct {
Name string
Duration duration
}
type songs struct {
Song []song
}
var favorites songs
if _, err := toml.Decode(blob, &favorites); err != nil {
log.Fatal(err)
}
for _, s := range favorites.Song {
fmt.Printf("%s (%s)\n", s.Name, s.Duration)
}
```
And you'll also need a `duration` type that satisfies the
`encoding.TextUnmarshaler` interface:
```go
type duration struct {
time.Duration
}
func (d *duration) UnmarshalText(text []byte) error {
var err error
d.Duration, err = time.ParseDuration(string(text))
return err
}
```
### More complex usage
Here's an example of how to load the example from the official spec page:
```toml
# This is a TOML document. Boom.
title = "TOML Example"
[owner]
name = "Tom Preston-Werner"
organization = "GitHub"
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
[database]
server = "192.168.1.1"
ports = [ 8001, 8001, 8002 ]
connection_max = 5000
enabled = true
[servers]
# You can indent as you please. Tabs or spaces. TOML don't care.
[servers.alpha]
ip = "10.0.0.1"
dc = "eqdc10"
[servers.beta]
ip = "10.0.0.2"
dc = "eqdc10"
[clients]
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
# Line breaks are OK when inside arrays
hosts = [
"alpha",
"omega"
]
```
And the corresponding Go types are:
```go
type tomlConfig struct {
Title string
Owner ownerInfo
DB database `toml:"database"`
Servers map[string]server
Clients clients
}
type ownerInfo struct {
Name string
Org string `toml:"organization"`
Bio string
DOB time.Time
}
type database struct {
Server string
Ports []int
ConnMax int `toml:"connection_max"`
Enabled bool
}
type server struct {
IP string
DC string
}
type clients struct {
Data [][]interface{}
Hosts []string
}
```
Note that a case insensitive match will be tried if an exact match can't be
found.
A working example of the above can be found in `_examples/example.{go,toml}`.

View File

@@ -1,509 +0,0 @@
package toml
import (
"fmt"
"io"
"io/ioutil"
"math"
"reflect"
"strings"
"time"
)
func e(format string, args ...interface{}) error {
return fmt.Errorf("toml: "+format, args...)
}
// Unmarshaler is the interface implemented by objects that can unmarshal a
// TOML description of themselves.
type Unmarshaler interface {
UnmarshalTOML(interface{}) error
}
// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`.
func Unmarshal(p []byte, v interface{}) error {
_, err := Decode(string(p), v)
return err
}
// Primitive is a TOML value that hasn't been decoded into a Go value.
// When using the various `Decode*` functions, the type `Primitive` may
// be given to any value, and its decoding will be delayed.
//
// A `Primitive` value can be decoded using the `PrimitiveDecode` function.
//
// The underlying representation of a `Primitive` value is subject to change.
// Do not rely on it.
//
// N.B. Primitive values are still parsed, so using them will only avoid
// the overhead of reflection. They can be useful when you don't know the
// exact type of TOML data until run time.
type Primitive struct {
undecoded interface{}
context Key
}
// DEPRECATED!
//
// Use MetaData.PrimitiveDecode instead.
func PrimitiveDecode(primValue Primitive, v interface{}) error {
md := MetaData{decoded: make(map[string]bool)}
return md.unify(primValue.undecoded, rvalue(v))
}
// PrimitiveDecode is just like the other `Decode*` functions, except it
// decodes a TOML value that has already been parsed. Valid primitive values
// can *only* be obtained from values filled by the decoder functions,
// including this method. (i.e., `v` may contain more `Primitive`
// values.)
//
// Meta data for primitive values is included in the meta data returned by
// the `Decode*` functions with one exception: keys returned by the Undecoded
// method will only reflect keys that were decoded. Namely, any keys hidden
// behind a Primitive will be considered undecoded. Executing this method will
// update the undecoded keys in the meta data. (See the example.)
func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
md.context = primValue.context
defer func() { md.context = nil }()
return md.unify(primValue.undecoded, rvalue(v))
}
// Decode will decode the contents of `data` in TOML format into a pointer
// `v`.
//
// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be
// used interchangeably.)
//
// TOML arrays of tables correspond to either a slice of structs or a slice
// of maps.
//
// TOML datetimes correspond to Go `time.Time` values.
//
// All other TOML types (float, string, int, bool and array) correspond
// to the obvious Go types.
//
// An exception to the above rules is if a type implements the
// encoding.TextUnmarshaler interface. In this case, any primitive TOML value
// (floats, strings, integers, booleans and datetimes) will be converted to
// a byte string and given to the value's UnmarshalText method. See the
// Unmarshaler example for a demonstration with time duration strings.
//
// Key mapping
//
// TOML keys can map to either keys in a Go map or field names in a Go
// struct. The special `toml` struct tag may be used to map TOML keys to
// struct fields that don't match the key name exactly. (See the example.)
// A case insensitive match to struct names will be tried if an exact match
// can't be found.
//
// The mapping between TOML values and Go values is loose. That is, there
// may exist TOML values that cannot be placed into your representation, and
// there may be parts of your representation that do not correspond to
// TOML values. This loose mapping can be made stricter by using the IsDefined
// and/or Undecoded methods on the MetaData returned.
//
// This decoder will not handle cyclic types. If a cyclic type is passed,
// `Decode` will not terminate.
func Decode(data string, v interface{}) (MetaData, error) {
rv := reflect.ValueOf(v)
if rv.Kind() != reflect.Ptr {
return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v))
}
if rv.IsNil() {
return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v))
}
p, err := parse(data)
if err != nil {
return MetaData{}, err
}
md := MetaData{
p.mapping, p.types, p.ordered,
make(map[string]bool, len(p.ordered)), nil,
}
return md, md.unify(p.mapping, indirect(rv))
}
// DecodeFile is just like Decode, except it will automatically read the
// contents of the file at `fpath` and decode it for you.
func DecodeFile(fpath string, v interface{}) (MetaData, error) {
bs, err := ioutil.ReadFile(fpath)
if err != nil {
return MetaData{}, err
}
return Decode(string(bs), v)
}
// DecodeReader is just like Decode, except it will consume all bytes
// from the reader and decode it for you.
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) {
bs, err := ioutil.ReadAll(r)
if err != nil {
return MetaData{}, err
}
return Decode(string(bs), v)
}
// unify performs a sort of type unification based on the structure of `rv`,
// which is the client representation.
//
// Any type mismatch produces an error. Finding a type that we don't know
// how to handle produces an unsupported type error.
func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
// Special case. Look for a `Primitive` value.
if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() {
// Save the undecoded data and the key context into the primitive
// value.
context := make(Key, len(md.context))
copy(context, md.context)
rv.Set(reflect.ValueOf(Primitive{
undecoded: data,
context: context,
}))
return nil
}
// Special case. Unmarshaler Interface support.
if rv.CanAddr() {
if v, ok := rv.Addr().Interface().(Unmarshaler); ok {
return v.UnmarshalTOML(data)
}
}
// Special case. Handle time.Time values specifically.
// TODO: Remove this code when we decide to drop support for Go 1.1.
// This isn't necessary in Go 1.2 because time.Time satisfies the encoding
// interfaces.
if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) {
return md.unifyDatetime(data, rv)
}
// Special case. Look for a value satisfying the TextUnmarshaler interface.
if v, ok := rv.Interface().(TextUnmarshaler); ok {
return md.unifyText(data, v)
}
// BUG(burntsushi)
// The behavior here is incorrect whenever a Go type satisfies the
// encoding.TextUnmarshaler interface but also corresponds to a TOML
// hash or array. In particular, the unmarshaler should only be applied
// to primitive TOML values. But at this point, it will be applied to
// all kinds of values and produce an incorrect error whenever those values
// are hashes or arrays (including arrays of tables).
k := rv.Kind()
// laziness
if k >= reflect.Int && k <= reflect.Uint64 {
return md.unifyInt(data, rv)
}
switch k {
case reflect.Ptr:
elem := reflect.New(rv.Type().Elem())
err := md.unify(data, reflect.Indirect(elem))
if err != nil {
return err
}
rv.Set(elem)
return nil
case reflect.Struct:
return md.unifyStruct(data, rv)
case reflect.Map:
return md.unifyMap(data, rv)
case reflect.Array:
return md.unifyArray(data, rv)
case reflect.Slice:
return md.unifySlice(data, rv)
case reflect.String:
return md.unifyString(data, rv)
case reflect.Bool:
return md.unifyBool(data, rv)
case reflect.Interface:
// we only support empty interfaces.
if rv.NumMethod() > 0 {
return e("unsupported type %s", rv.Type())
}
return md.unifyAnything(data, rv)
case reflect.Float32:
fallthrough
case reflect.Float64:
return md.unifyFloat64(data, rv)
}
return e("unsupported type %s", rv.Kind())
}
func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
tmap, ok := mapping.(map[string]interface{})
if !ok {
if mapping == nil {
return nil
}
return e("type mismatch for %s: expected table but found %T",
rv.Type().String(), mapping)
}
for key, datum := range tmap {
var f *field
fields := cachedTypeFields(rv.Type())
for i := range fields {
ff := &fields[i]
if ff.name == key {
f = ff
break
}
if f == nil && strings.EqualFold(ff.name, key) {
f = ff
}
}
if f != nil {
subv := rv
for _, i := range f.index {
subv = indirect(subv.Field(i))
}
if isUnifiable(subv) {
md.decoded[md.context.add(key).String()] = true
md.context = append(md.context, key)
if err := md.unify(datum, subv); err != nil {
return err
}
md.context = md.context[0 : len(md.context)-1]
} else if f.name != "" {
// Bad user! No soup for you!
return e("cannot write unexported field %s.%s",
rv.Type().String(), f.name)
}
}
}
return nil
}
func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error {
tmap, ok := mapping.(map[string]interface{})
if !ok {
if tmap == nil {
return nil
}
return badtype("map", mapping)
}
if rv.IsNil() {
rv.Set(reflect.MakeMap(rv.Type()))
}
for k, v := range tmap {
md.decoded[md.context.add(k).String()] = true
md.context = append(md.context, k)
rvkey := indirect(reflect.New(rv.Type().Key()))
rvval := reflect.Indirect(reflect.New(rv.Type().Elem()))
if err := md.unify(v, rvval); err != nil {
return err
}
md.context = md.context[0 : len(md.context)-1]
rvkey.SetString(k)
rv.SetMapIndex(rvkey, rvval)
}
return nil
}
func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error {
datav := reflect.ValueOf(data)
if datav.Kind() != reflect.Slice {
if !datav.IsValid() {
return nil
}
return badtype("slice", data)
}
sliceLen := datav.Len()
if sliceLen != rv.Len() {
return e("expected array length %d; got TOML array of length %d",
rv.Len(), sliceLen)
}
return md.unifySliceArray(datav, rv)
}
func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
datav := reflect.ValueOf(data)
if datav.Kind() != reflect.Slice {
if !datav.IsValid() {
return nil
}
return badtype("slice", data)
}
n := datav.Len()
if rv.IsNil() || rv.Cap() < n {
rv.Set(reflect.MakeSlice(rv.Type(), n, n))
}
rv.SetLen(n)
return md.unifySliceArray(datav, rv)
}
func (md *MetaData) unifySliceArray(data, rv reflect.Value) error {
sliceLen := data.Len()
for i := 0; i < sliceLen; i++ {
v := data.Index(i).Interface()
sliceval := indirect(rv.Index(i))
if err := md.unify(v, sliceval); err != nil {
return err
}
}
return nil
}
func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error {
if _, ok := data.(time.Time); ok {
rv.Set(reflect.ValueOf(data))
return nil
}
return badtype("time.Time", data)
}
func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
if s, ok := data.(string); ok {
rv.SetString(s)
return nil
}
return badtype("string", data)
}
func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
if num, ok := data.(float64); ok {
switch rv.Kind() {
case reflect.Float32:
fallthrough
case reflect.Float64:
rv.SetFloat(num)
default:
panic("bug")
}
return nil
}
return badtype("float", data)
}
func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error {
if num, ok := data.(int64); ok {
if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 {
switch rv.Kind() {
case reflect.Int, reflect.Int64:
// No bounds checking necessary.
case reflect.Int8:
if num < math.MinInt8 || num > math.MaxInt8 {
return e("value %d is out of range for int8", num)
}
case reflect.Int16:
if num < math.MinInt16 || num > math.MaxInt16 {
return e("value %d is out of range for int16", num)
}
case reflect.Int32:
if num < math.MinInt32 || num > math.MaxInt32 {
return e("value %d is out of range for int32", num)
}
}
rv.SetInt(num)
} else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 {
unum := uint64(num)
switch rv.Kind() {
case reflect.Uint, reflect.Uint64:
// No bounds checking necessary.
case reflect.Uint8:
if num < 0 || unum > math.MaxUint8 {
return e("value %d is out of range for uint8", num)
}
case reflect.Uint16:
if num < 0 || unum > math.MaxUint16 {
return e("value %d is out of range for uint16", num)
}
case reflect.Uint32:
if num < 0 || unum > math.MaxUint32 {
return e("value %d is out of range for uint32", num)
}
}
rv.SetUint(unum)
} else {
panic("unreachable")
}
return nil
}
return badtype("integer", data)
}
func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
if b, ok := data.(bool); ok {
rv.SetBool(b)
return nil
}
return badtype("boolean", data)
}
func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
rv.Set(reflect.ValueOf(data))
return nil
}
func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
var s string
switch sdata := data.(type) {
case TextMarshaler:
text, err := sdata.MarshalText()
if err != nil {
return err
}
s = string(text)
case fmt.Stringer:
s = sdata.String()
case string:
s = sdata
case bool:
s = fmt.Sprintf("%v", sdata)
case int64:
s = fmt.Sprintf("%d", sdata)
case float64:
s = fmt.Sprintf("%f", sdata)
default:
return badtype("primitive (string-like)", data)
}
if err := v.UnmarshalText([]byte(s)); err != nil {
return err
}
return nil
}
// rvalue returns a reflect.Value of `v`. All pointers are resolved.
func rvalue(v interface{}) reflect.Value {
return indirect(reflect.ValueOf(v))
}
// indirect returns the value pointed to by a pointer.
// Pointers are followed until the value is not a pointer.
// New values are allocated for each nil pointer.
//
// An exception to this rule is if the value satisfies an interface of
// interest to us (like encoding.TextUnmarshaler).
func indirect(v reflect.Value) reflect.Value {
if v.Kind() != reflect.Ptr {
if v.CanSet() {
pv := v.Addr()
if _, ok := pv.Interface().(TextUnmarshaler); ok {
return pv
}
}
return v
}
if v.IsNil() {
v.Set(reflect.New(v.Type().Elem()))
}
return indirect(reflect.Indirect(v))
}
func isUnifiable(rv reflect.Value) bool {
if rv.CanSet() {
return true
}
if _, ok := rv.Interface().(TextUnmarshaler); ok {
return true
}
return false
}
func badtype(expected string, data interface{}) error {
return e("cannot load TOML value of type %T into a Go %s", data, expected)
}

View File

@@ -1,121 +0,0 @@
package toml
import "strings"
// MetaData allows access to meta information about TOML data that may not
// be inferrable via reflection. In particular, whether a key has been defined
// and the TOML type of a key.
type MetaData struct {
mapping map[string]interface{}
types map[string]tomlType
keys []Key
decoded map[string]bool
context Key // Used only during decoding.
}
// IsDefined returns true if the key given exists in the TOML data. The key
// should be specified hierarchially. e.g.,
//
// // access the TOML key 'a.b.c'
// IsDefined("a", "b", "c")
//
// IsDefined will return false if an empty key given. Keys are case sensitive.
func (md *MetaData) IsDefined(key ...string) bool {
if len(key) == 0 {
return false
}
var hash map[string]interface{}
var ok bool
var hashOrVal interface{} = md.mapping
for _, k := range key {
if hash, ok = hashOrVal.(map[string]interface{}); !ok {
return false
}
if hashOrVal, ok = hash[k]; !ok {
return false
}
}
return true
}
// Type returns a string representation of the type of the key specified.
//
// Type will return the empty string if given an empty key or a key that
// does not exist. Keys are case sensitive.
func (md *MetaData) Type(key ...string) string {
fullkey := strings.Join(key, ".")
if typ, ok := md.types[fullkey]; ok {
return typ.typeString()
}
return ""
}
// Key is the type of any TOML key, including key groups. Use (MetaData).Keys
// to get values of this type.
type Key []string
func (k Key) String() string {
return strings.Join(k, ".")
}
func (k Key) maybeQuotedAll() string {
var ss []string
for i := range k {
ss = append(ss, k.maybeQuoted(i))
}
return strings.Join(ss, ".")
}
func (k Key) maybeQuoted(i int) string {
quote := false
for _, c := range k[i] {
if !isBareKeyChar(c) {
quote = true
break
}
}
if quote {
return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\""
}
return k[i]
}
func (k Key) add(piece string) Key {
newKey := make(Key, len(k)+1)
copy(newKey, k)
newKey[len(k)] = piece
return newKey
}
// Keys returns a slice of every key in the TOML data, including key groups.
// Each key is itself a slice, where the first element is the top of the
// hierarchy and the last is the most specific.
//
// The list will have the same order as the keys appeared in the TOML data.
//
// All keys returned are non-empty.
func (md *MetaData) Keys() []Key {
return md.keys
}
// Undecoded returns all keys that have not been decoded in the order in which
// they appear in the original TOML document.
//
// This includes keys that haven't been decoded because of a Primitive value.
// Once the Primitive value is decoded, the keys will be considered decoded.
//
// Also note that decoding into an empty interface will result in no decoding,
// and so no keys will be considered decoded.
//
// In this sense, the Undecoded keys correspond to keys in the TOML document
// that do not have a concrete type in your representation.
func (md *MetaData) Undecoded() []Key {
undecoded := make([]Key, 0, len(md.keys))
for _, key := range md.keys {
if !md.decoded[key.String()] {
undecoded = append(undecoded, key)
}
}
return undecoded
}

View File

@@ -1,27 +0,0 @@
/*
Package toml provides facilities for decoding and encoding TOML configuration
files via reflection. There is also support for delaying decoding with
the Primitive type, and querying the set of keys in a TOML document with the
MetaData type.
The specification implemented: https://github.com/toml-lang/toml
The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify
whether a file is a valid TOML document. It can also be used to print the
type of each key in a TOML document.
Testing
There are two important types of tests used for this package. The first is
contained inside '*_test.go' files and uses the standard Go unit testing
framework. These tests are primarily devoted to holistically testing the
decoder and encoder.
The second type of testing is used to verify the implementation's adherence
to the TOML specification. These tests have been factored into their own
project: https://github.com/BurntSushi/toml-test
The reason the tests are in a separate project is so that they can be used by
any implementation of TOML. Namely, it is language agnostic.
*/
package toml

View File

@@ -1,568 +0,0 @@
package toml
import (
"bufio"
"errors"
"fmt"
"io"
"reflect"
"sort"
"strconv"
"strings"
"time"
)
type tomlEncodeError struct{ error }
var (
errArrayMixedElementTypes = errors.New(
"toml: cannot encode array with mixed element types")
errArrayNilElement = errors.New(
"toml: cannot encode array with nil element")
errNonString = errors.New(
"toml: cannot encode a map with non-string key type")
errAnonNonStruct = errors.New(
"toml: cannot encode an anonymous field that is not a struct")
errArrayNoTable = errors.New(
"toml: TOML array element cannot contain a table")
errNoKey = errors.New(
"toml: top-level values must be Go maps or structs")
errAnything = errors.New("") // used in testing
)
var quotedReplacer = strings.NewReplacer(
"\t", "\\t",
"\n", "\\n",
"\r", "\\r",
"\"", "\\\"",
"\\", "\\\\",
)
// Encoder controls the encoding of Go values to a TOML document to some
// io.Writer.
//
// The indentation level can be controlled with the Indent field.
type Encoder struct {
// A single indentation level. By default it is two spaces.
Indent string
// hasWritten is whether we have written any output to w yet.
hasWritten bool
w *bufio.Writer
}
// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer
// given. By default, a single indentation level is 2 spaces.
func NewEncoder(w io.Writer) *Encoder {
return &Encoder{
w: bufio.NewWriter(w),
Indent: " ",
}
}
// Encode writes a TOML representation of the Go value to the underlying
// io.Writer. If the value given cannot be encoded to a valid TOML document,
// then an error is returned.
//
// The mapping between Go values and TOML values should be precisely the same
// as for the Decode* functions. Similarly, the TextMarshaler interface is
// supported by encoding the resulting bytes as strings. (If you want to write
// arbitrary binary data then you will need to use something like base64 since
// TOML does not have any binary types.)
//
// When encoding TOML hashes (i.e., Go maps or structs), keys without any
// sub-hashes are encoded first.
//
// If a Go map is encoded, then its keys are sorted alphabetically for
// deterministic output. More control over this behavior may be provided if
// there is demand for it.
//
// Encoding Go values without a corresponding TOML representation---like map
// types with non-string keys---will cause an error to be returned. Similarly
// for mixed arrays/slices, arrays/slices with nil elements, embedded
// non-struct types and nested slices containing maps or structs.
// (e.g., [][]map[string]string is not allowed but []map[string]string is OK
// and so is []map[string][]string.)
func (enc *Encoder) Encode(v interface{}) error {
rv := eindirect(reflect.ValueOf(v))
if err := enc.safeEncode(Key([]string{}), rv); err != nil {
return err
}
return enc.w.Flush()
}
func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) {
defer func() {
if r := recover(); r != nil {
if terr, ok := r.(tomlEncodeError); ok {
err = terr.error
return
}
panic(r)
}
}()
enc.encode(key, rv)
return nil
}
func (enc *Encoder) encode(key Key, rv reflect.Value) {
// Special case. Time needs to be in ISO8601 format.
// Special case. If we can marshal the type to text, then we used that.
// Basically, this prevents the encoder for handling these types as
// generic structs (or whatever the underlying type of a TextMarshaler is).
switch rv.Interface().(type) {
case time.Time, TextMarshaler:
enc.keyEqElement(key, rv)
return
}
k := rv.Kind()
switch k {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
reflect.Uint64,
reflect.Float32, reflect.Float64, reflect.String, reflect.Bool:
enc.keyEqElement(key, rv)
case reflect.Array, reflect.Slice:
if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) {
enc.eArrayOfTables(key, rv)
} else {
enc.keyEqElement(key, rv)
}
case reflect.Interface:
if rv.IsNil() {
return
}
enc.encode(key, rv.Elem())
case reflect.Map:
if rv.IsNil() {
return
}
enc.eTable(key, rv)
case reflect.Ptr:
if rv.IsNil() {
return
}
enc.encode(key, rv.Elem())
case reflect.Struct:
enc.eTable(key, rv)
default:
panic(e("unsupported type for key '%s': %s", key, k))
}
}
// eElement encodes any value that can be an array element (primitives and
// arrays).
func (enc *Encoder) eElement(rv reflect.Value) {
switch v := rv.Interface().(type) {
case time.Time:
// Special case time.Time as a primitive. Has to come before
// TextMarshaler below because time.Time implements
// encoding.TextMarshaler, but we need to always use UTC.
enc.wf(v.UTC().Format("2006-01-02T15:04:05Z"))
return
case TextMarshaler:
// Special case. Use text marshaler if it's available for this value.
if s, err := v.MarshalText(); err != nil {
encPanic(err)
} else {
enc.writeQuoted(string(s))
}
return
}
switch rv.Kind() {
case reflect.Bool:
enc.wf(strconv.FormatBool(rv.Bool()))
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
reflect.Int64:
enc.wf(strconv.FormatInt(rv.Int(), 10))
case reflect.Uint, reflect.Uint8, reflect.Uint16,
reflect.Uint32, reflect.Uint64:
enc.wf(strconv.FormatUint(rv.Uint(), 10))
case reflect.Float32:
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32)))
case reflect.Float64:
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64)))
case reflect.Array, reflect.Slice:
enc.eArrayOrSliceElement(rv)
case reflect.Interface:
enc.eElement(rv.Elem())
case reflect.String:
enc.writeQuoted(rv.String())
default:
panic(e("unexpected primitive type: %s", rv.Kind()))
}
}
// By the TOML spec, all floats must have a decimal with at least one
// number on either side.
func floatAddDecimal(fstr string) string {
if !strings.Contains(fstr, ".") {
return fstr + ".0"
}
return fstr
}
func (enc *Encoder) writeQuoted(s string) {
enc.wf("\"%s\"", quotedReplacer.Replace(s))
}
func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) {
length := rv.Len()
enc.wf("[")
for i := 0; i < length; i++ {
elem := rv.Index(i)
enc.eElement(elem)
if i != length-1 {
enc.wf(", ")
}
}
enc.wf("]")
}
func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) {
if len(key) == 0 {
encPanic(errNoKey)
}
for i := 0; i < rv.Len(); i++ {
trv := rv.Index(i)
if isNil(trv) {
continue
}
panicIfInvalidKey(key)
enc.newline()
enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll())
enc.newline()
enc.eMapOrStruct(key, trv)
}
}
func (enc *Encoder) eTable(key Key, rv reflect.Value) {
panicIfInvalidKey(key)
if len(key) == 1 {
// Output an extra newline between top-level tables.
// (The newline isn't written if nothing else has been written though.)
enc.newline()
}
if len(key) > 0 {
enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll())
enc.newline()
}
enc.eMapOrStruct(key, rv)
}
func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) {
switch rv := eindirect(rv); rv.Kind() {
case reflect.Map:
enc.eMap(key, rv)
case reflect.Struct:
enc.eStruct(key, rv)
default:
panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String())
}
}
func (enc *Encoder) eMap(key Key, rv reflect.Value) {
rt := rv.Type()
if rt.Key().Kind() != reflect.String {
encPanic(errNonString)
}
// Sort keys so that we have deterministic output. And write keys directly
// underneath this key first, before writing sub-structs or sub-maps.
var mapKeysDirect, mapKeysSub []string
for _, mapKey := range rv.MapKeys() {
k := mapKey.String()
if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) {
mapKeysSub = append(mapKeysSub, k)
} else {
mapKeysDirect = append(mapKeysDirect, k)
}
}
var writeMapKeys = func(mapKeys []string) {
sort.Strings(mapKeys)
for _, mapKey := range mapKeys {
mrv := rv.MapIndex(reflect.ValueOf(mapKey))
if isNil(mrv) {
// Don't write anything for nil fields.
continue
}
enc.encode(key.add(mapKey), mrv)
}
}
writeMapKeys(mapKeysDirect)
writeMapKeys(mapKeysSub)
}
func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
// Write keys for fields directly under this key first, because if we write
// a field that creates a new table, then all keys under it will be in that
// table (not the one we're writing here).
rt := rv.Type()
var fieldsDirect, fieldsSub [][]int
var addFields func(rt reflect.Type, rv reflect.Value, start []int)
addFields = func(rt reflect.Type, rv reflect.Value, start []int) {
for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i)
// skip unexported fields
if f.PkgPath != "" && !f.Anonymous {
continue
}
frv := rv.Field(i)
if f.Anonymous {
t := f.Type
switch t.Kind() {
case reflect.Struct:
// Treat anonymous struct fields with
// tag names as though they are not
// anonymous, like encoding/json does.
if getOptions(f.Tag).name == "" {
addFields(t, frv, f.Index)
continue
}
case reflect.Ptr:
if t.Elem().Kind() == reflect.Struct &&
getOptions(f.Tag).name == "" {
if !frv.IsNil() {
addFields(t.Elem(), frv.Elem(), f.Index)
}
continue
}
// Fall through to the normal field encoding logic below
// for non-struct anonymous fields.
}
}
if typeIsHash(tomlTypeOfGo(frv)) {
fieldsSub = append(fieldsSub, append(start, f.Index...))
} else {
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
}
}
}
addFields(rt, rv, nil)
var writeFields = func(fields [][]int) {
for _, fieldIndex := range fields {
sft := rt.FieldByIndex(fieldIndex)
sf := rv.FieldByIndex(fieldIndex)
if isNil(sf) {
// Don't write anything for nil fields.
continue
}
opts := getOptions(sft.Tag)
if opts.skip {
continue
}
keyName := sft.Name
if opts.name != "" {
keyName = opts.name
}
if opts.omitempty && isEmpty(sf) {
continue
}
if opts.omitzero && isZero(sf) {
continue
}
enc.encode(key.add(keyName), sf)
}
}
writeFields(fieldsDirect)
writeFields(fieldsSub)
}
// tomlTypeName returns the TOML type name of the Go value's type. It is
// used to determine whether the types of array elements are mixed (which is
// forbidden). If the Go value is nil, then it is illegal for it to be an array
// element, and valueIsNil is returned as true.
// Returns the TOML type of a Go value. The type may be `nil`, which means
// no concrete TOML type could be found.
func tomlTypeOfGo(rv reflect.Value) tomlType {
if isNil(rv) || !rv.IsValid() {
return nil
}
switch rv.Kind() {
case reflect.Bool:
return tomlBool
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
reflect.Uint64:
return tomlInteger
case reflect.Float32, reflect.Float64:
return tomlFloat
case reflect.Array, reflect.Slice:
if typeEqual(tomlHash, tomlArrayType(rv)) {
return tomlArrayHash
}
return tomlArray
case reflect.Ptr, reflect.Interface:
return tomlTypeOfGo(rv.Elem())
case reflect.String:
return tomlString
case reflect.Map:
return tomlHash
case reflect.Struct:
switch rv.Interface().(type) {
case time.Time:
return tomlDatetime
case TextMarshaler:
return tomlString
default:
return tomlHash
}
default:
panic("unexpected reflect.Kind: " + rv.Kind().String())
}
}
// tomlArrayType returns the element type of a TOML array. The type returned
// may be nil if it cannot be determined (e.g., a nil slice or a zero length
// slize). This function may also panic if it finds a type that cannot be
// expressed in TOML (such as nil elements, heterogeneous arrays or directly
// nested arrays of tables).
func tomlArrayType(rv reflect.Value) tomlType {
if isNil(rv) || !rv.IsValid() || rv.Len() == 0 {
return nil
}
firstType := tomlTypeOfGo(rv.Index(0))
if firstType == nil {
encPanic(errArrayNilElement)
}
rvlen := rv.Len()
for i := 1; i < rvlen; i++ {
elem := rv.Index(i)
switch elemType := tomlTypeOfGo(elem); {
case elemType == nil:
encPanic(errArrayNilElement)
case !typeEqual(firstType, elemType):
encPanic(errArrayMixedElementTypes)
}
}
// If we have a nested array, then we must make sure that the nested
// array contains ONLY primitives.
// This checks arbitrarily nested arrays.
if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) {
nest := tomlArrayType(eindirect(rv.Index(0)))
if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) {
encPanic(errArrayNoTable)
}
}
return firstType
}
type tagOptions struct {
skip bool // "-"
name string
omitempty bool
omitzero bool
}
func getOptions(tag reflect.StructTag) tagOptions {
t := tag.Get("toml")
if t == "-" {
return tagOptions{skip: true}
}
var opts tagOptions
parts := strings.Split(t, ",")
opts.name = parts[0]
for _, s := range parts[1:] {
switch s {
case "omitempty":
opts.omitempty = true
case "omitzero":
opts.omitzero = true
}
}
return opts
}
func isZero(rv reflect.Value) bool {
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return rv.Int() == 0
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return rv.Uint() == 0
case reflect.Float32, reflect.Float64:
return rv.Float() == 0.0
}
return false
}
func isEmpty(rv reflect.Value) bool {
switch rv.Kind() {
case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
return rv.Len() == 0
case reflect.Bool:
return !rv.Bool()
}
return false
}
func (enc *Encoder) newline() {
if enc.hasWritten {
enc.wf("\n")
}
}
func (enc *Encoder) keyEqElement(key Key, val reflect.Value) {
if len(key) == 0 {
encPanic(errNoKey)
}
panicIfInvalidKey(key)
enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
enc.eElement(val)
enc.newline()
}
func (enc *Encoder) wf(format string, v ...interface{}) {
if _, err := fmt.Fprintf(enc.w, format, v...); err != nil {
encPanic(err)
}
enc.hasWritten = true
}
func (enc *Encoder) indentStr(key Key) string {
return strings.Repeat(enc.Indent, len(key)-1)
}
func encPanic(err error) {
panic(tomlEncodeError{err})
}
func eindirect(v reflect.Value) reflect.Value {
switch v.Kind() {
case reflect.Ptr, reflect.Interface:
return eindirect(v.Elem())
default:
return v
}
}
func isNil(rv reflect.Value) bool {
switch rv.Kind() {
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
return rv.IsNil()
default:
return false
}
}
func panicIfInvalidKey(key Key) {
for _, k := range key {
if len(k) == 0 {
encPanic(e("Key '%s' is not a valid table name. Key names "+
"cannot be empty.", key.maybeQuotedAll()))
}
}
}
func isValidKeyName(s string) bool {
return len(s) != 0
}

View File

@@ -1,19 +0,0 @@
// +build go1.2
package toml
// In order to support Go 1.1, we define our own TextMarshaler and
// TextUnmarshaler types. For Go 1.2+, we just alias them with the
// standard library interfaces.
import (
"encoding"
)
// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
// so that Go 1.1 can be supported.
type TextMarshaler encoding.TextMarshaler
// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
// here so that Go 1.1 can be supported.
type TextUnmarshaler encoding.TextUnmarshaler

View File

@@ -1,18 +0,0 @@
// +build !go1.2
package toml
// These interfaces were introduced in Go 1.2, so we add them manually when
// compiling for Go 1.1.
// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
// so that Go 1.1 can be supported.
type TextMarshaler interface {
MarshalText() (text []byte, err error)
}
// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
// here so that Go 1.1 can be supported.
type TextUnmarshaler interface {
UnmarshalText(text []byte) error
}

View File

@@ -1,953 +0,0 @@
package toml
import (
"fmt"
"strings"
"unicode"
"unicode/utf8"
)
type itemType int
const (
itemError itemType = iota
itemNIL // used in the parser to indicate no type
itemEOF
itemText
itemString
itemRawString
itemMultilineString
itemRawMultilineString
itemBool
itemInteger
itemFloat
itemDatetime
itemArray // the start of an array
itemArrayEnd
itemTableStart
itemTableEnd
itemArrayTableStart
itemArrayTableEnd
itemKeyStart
itemCommentStart
itemInlineTableStart
itemInlineTableEnd
)
const (
eof = 0
comma = ','
tableStart = '['
tableEnd = ']'
arrayTableStart = '['
arrayTableEnd = ']'
tableSep = '.'
keySep = '='
arrayStart = '['
arrayEnd = ']'
commentStart = '#'
stringStart = '"'
stringEnd = '"'
rawStringStart = '\''
rawStringEnd = '\''
inlineTableStart = '{'
inlineTableEnd = '}'
)
type stateFn func(lx *lexer) stateFn
type lexer struct {
input string
start int
pos int
line int
state stateFn
items chan item
// Allow for backing up up to three runes.
// This is necessary because TOML contains 3-rune tokens (""" and ''').
prevWidths [3]int
nprev int // how many of prevWidths are in use
// If we emit an eof, we can still back up, but it is not OK to call
// next again.
atEOF bool
// A stack of state functions used to maintain context.
// The idea is to reuse parts of the state machine in various places.
// For example, values can appear at the top level or within arbitrarily
// nested arrays. The last state on the stack is used after a value has
// been lexed. Similarly for comments.
stack []stateFn
}
type item struct {
typ itemType
val string
line int
}
func (lx *lexer) nextItem() item {
for {
select {
case item := <-lx.items:
return item
default:
lx.state = lx.state(lx)
}
}
}
func lex(input string) *lexer {
lx := &lexer{
input: input,
state: lexTop,
line: 1,
items: make(chan item, 10),
stack: make([]stateFn, 0, 10),
}
return lx
}
func (lx *lexer) push(state stateFn) {
lx.stack = append(lx.stack, state)
}
func (lx *lexer) pop() stateFn {
if len(lx.stack) == 0 {
return lx.errorf("BUG in lexer: no states to pop")
}
last := lx.stack[len(lx.stack)-1]
lx.stack = lx.stack[0 : len(lx.stack)-1]
return last
}
func (lx *lexer) current() string {
return lx.input[lx.start:lx.pos]
}
func (lx *lexer) emit(typ itemType) {
lx.items <- item{typ, lx.current(), lx.line}
lx.start = lx.pos
}
func (lx *lexer) emitTrim(typ itemType) {
lx.items <- item{typ, strings.TrimSpace(lx.current()), lx.line}
lx.start = lx.pos
}
func (lx *lexer) next() (r rune) {
if lx.atEOF {
panic("next called after EOF")
}
if lx.pos >= len(lx.input) {
lx.atEOF = true
return eof
}
if lx.input[lx.pos] == '\n' {
lx.line++
}
lx.prevWidths[2] = lx.prevWidths[1]
lx.prevWidths[1] = lx.prevWidths[0]
if lx.nprev < 3 {
lx.nprev++
}
r, w := utf8.DecodeRuneInString(lx.input[lx.pos:])
lx.prevWidths[0] = w
lx.pos += w
return r
}
// ignore skips over the pending input before this point.
func (lx *lexer) ignore() {
lx.start = lx.pos
}
// backup steps back one rune. Can be called only twice between calls to next.
func (lx *lexer) backup() {
if lx.atEOF {
lx.atEOF = false
return
}
if lx.nprev < 1 {
panic("backed up too far")
}
w := lx.prevWidths[0]
lx.prevWidths[0] = lx.prevWidths[1]
lx.prevWidths[1] = lx.prevWidths[2]
lx.nprev--
lx.pos -= w
if lx.pos < len(lx.input) && lx.input[lx.pos] == '\n' {
lx.line--
}
}
// accept consumes the next rune if it's equal to `valid`.
func (lx *lexer) accept(valid rune) bool {
if lx.next() == valid {
return true
}
lx.backup()
return false
}
// peek returns but does not consume the next rune in the input.
func (lx *lexer) peek() rune {
r := lx.next()
lx.backup()
return r
}
// skip ignores all input that matches the given predicate.
func (lx *lexer) skip(pred func(rune) bool) {
for {
r := lx.next()
if pred(r) {
continue
}
lx.backup()
lx.ignore()
return
}
}
// errorf stops all lexing by emitting an error and returning `nil`.
// Note that any value that is a character is escaped if it's a special
// character (newlines, tabs, etc.).
func (lx *lexer) errorf(format string, values ...interface{}) stateFn {
lx.items <- item{
itemError,
fmt.Sprintf(format, values...),
lx.line,
}
return nil
}
// lexTop consumes elements at the top level of TOML data.
func lexTop(lx *lexer) stateFn {
r := lx.next()
if isWhitespace(r) || isNL(r) {
return lexSkip(lx, lexTop)
}
switch r {
case commentStart:
lx.push(lexTop)
return lexCommentStart
case tableStart:
return lexTableStart
case eof:
if lx.pos > lx.start {
return lx.errorf("unexpected EOF")
}
lx.emit(itemEOF)
return nil
}
// At this point, the only valid item can be a key, so we back up
// and let the key lexer do the rest.
lx.backup()
lx.push(lexTopEnd)
return lexKeyStart
}
// lexTopEnd is entered whenever a top-level item has been consumed. (A value
// or a table.) It must see only whitespace, and will turn back to lexTop
// upon a newline. If it sees EOF, it will quit the lexer successfully.
func lexTopEnd(lx *lexer) stateFn {
r := lx.next()
switch {
case r == commentStart:
// a comment will read to a newline for us.
lx.push(lexTop)
return lexCommentStart
case isWhitespace(r):
return lexTopEnd
case isNL(r):
lx.ignore()
return lexTop
case r == eof:
lx.emit(itemEOF)
return nil
}
return lx.errorf("expected a top-level item to end with a newline, "+
"comment, or EOF, but got %q instead", r)
}
// lexTable lexes the beginning of a table. Namely, it makes sure that
// it starts with a character other than '.' and ']'.
// It assumes that '[' has already been consumed.
// It also handles the case that this is an item in an array of tables.
// e.g., '[[name]]'.
func lexTableStart(lx *lexer) stateFn {
if lx.peek() == arrayTableStart {
lx.next()
lx.emit(itemArrayTableStart)
lx.push(lexArrayTableEnd)
} else {
lx.emit(itemTableStart)
lx.push(lexTableEnd)
}
return lexTableNameStart
}
func lexTableEnd(lx *lexer) stateFn {
lx.emit(itemTableEnd)
return lexTopEnd
}
func lexArrayTableEnd(lx *lexer) stateFn {
if r := lx.next(); r != arrayTableEnd {
return lx.errorf("expected end of table array name delimiter %q, "+
"but got %q instead", arrayTableEnd, r)
}
lx.emit(itemArrayTableEnd)
return lexTopEnd
}
func lexTableNameStart(lx *lexer) stateFn {
lx.skip(isWhitespace)
switch r := lx.peek(); {
case r == tableEnd || r == eof:
return lx.errorf("unexpected end of table name " +
"(table names cannot be empty)")
case r == tableSep:
return lx.errorf("unexpected table separator " +
"(table names cannot be empty)")
case r == stringStart || r == rawStringStart:
lx.ignore()
lx.push(lexTableNameEnd)
return lexValue // reuse string lexing
default:
return lexBareTableName
}
}
// lexBareTableName lexes the name of a table. It assumes that at least one
// valid character for the table has already been read.
func lexBareTableName(lx *lexer) stateFn {
r := lx.next()
if isBareKeyChar(r) {
return lexBareTableName
}
lx.backup()
lx.emit(itemText)
return lexTableNameEnd
}
// lexTableNameEnd reads the end of a piece of a table name, optionally
// consuming whitespace.
func lexTableNameEnd(lx *lexer) stateFn {
lx.skip(isWhitespace)
switch r := lx.next(); {
case isWhitespace(r):
return lexTableNameEnd
case r == tableSep:
lx.ignore()
return lexTableNameStart
case r == tableEnd:
return lx.pop()
default:
return lx.errorf("expected '.' or ']' to end table name, "+
"but got %q instead", r)
}
}
// lexKeyStart consumes a key name up until the first non-whitespace character.
// lexKeyStart will ignore whitespace.
func lexKeyStart(lx *lexer) stateFn {
r := lx.peek()
switch {
case r == keySep:
return lx.errorf("unexpected key separator %q", keySep)
case isWhitespace(r) || isNL(r):
lx.next()
return lexSkip(lx, lexKeyStart)
case r == stringStart || r == rawStringStart:
lx.ignore()
lx.emit(itemKeyStart)
lx.push(lexKeyEnd)
return lexValue // reuse string lexing
default:
lx.ignore()
lx.emit(itemKeyStart)
return lexBareKey
}
}
// lexBareKey consumes the text of a bare key. Assumes that the first character
// (which is not whitespace) has not yet been consumed.
func lexBareKey(lx *lexer) stateFn {
switch r := lx.next(); {
case isBareKeyChar(r):
return lexBareKey
case isWhitespace(r):
lx.backup()
lx.emit(itemText)
return lexKeyEnd
case r == keySep:
lx.backup()
lx.emit(itemText)
return lexKeyEnd
default:
return lx.errorf("bare keys cannot contain %q", r)
}
}
// lexKeyEnd consumes the end of a key and trims whitespace (up to the key
// separator).
func lexKeyEnd(lx *lexer) stateFn {
switch r := lx.next(); {
case r == keySep:
return lexSkip(lx, lexValue)
case isWhitespace(r):
return lexSkip(lx, lexKeyEnd)
default:
return lx.errorf("expected key separator %q, but got %q instead",
keySep, r)
}
}
// lexValue starts the consumption of a value anywhere a value is expected.
// lexValue will ignore whitespace.
// After a value is lexed, the last state on the next is popped and returned.
func lexValue(lx *lexer) stateFn {
// We allow whitespace to precede a value, but NOT newlines.
// In array syntax, the array states are responsible for ignoring newlines.
r := lx.next()
switch {
case isWhitespace(r):
return lexSkip(lx, lexValue)
case isDigit(r):
lx.backup() // avoid an extra state and use the same as above
return lexNumberOrDateStart
}
switch r {
case arrayStart:
lx.ignore()
lx.emit(itemArray)
return lexArrayValue
case inlineTableStart:
lx.ignore()
lx.emit(itemInlineTableStart)
return lexInlineTableValue
case stringStart:
if lx.accept(stringStart) {
if lx.accept(stringStart) {
lx.ignore() // Ignore """
return lexMultilineString
}
lx.backup()
}
lx.ignore() // ignore the '"'
return lexString
case rawStringStart:
if lx.accept(rawStringStart) {
if lx.accept(rawStringStart) {
lx.ignore() // Ignore """
return lexMultilineRawString
}
lx.backup()
}
lx.ignore() // ignore the "'"
return lexRawString
case '+', '-':
return lexNumberStart
case '.': // special error case, be kind to users
return lx.errorf("floats must start with a digit, not '.'")
}
if unicode.IsLetter(r) {
// Be permissive here; lexBool will give a nice error if the
// user wrote something like
// x = foo
// (i.e. not 'true' or 'false' but is something else word-like.)
lx.backup()
return lexBool
}
return lx.errorf("expected value but found %q instead", r)
}
// lexArrayValue consumes one value in an array. It assumes that '[' or ','
// have already been consumed. All whitespace and newlines are ignored.
func lexArrayValue(lx *lexer) stateFn {
r := lx.next()
switch {
case isWhitespace(r) || isNL(r):
return lexSkip(lx, lexArrayValue)
case r == commentStart:
lx.push(lexArrayValue)
return lexCommentStart
case r == comma:
return lx.errorf("unexpected comma")
case r == arrayEnd:
// NOTE(caleb): The spec isn't clear about whether you can have
// a trailing comma or not, so we'll allow it.
return lexArrayEnd
}
lx.backup()
lx.push(lexArrayValueEnd)
return lexValue
}
// lexArrayValueEnd consumes everything between the end of an array value and
// the next value (or the end of the array): it ignores whitespace and newlines
// and expects either a ',' or a ']'.
func lexArrayValueEnd(lx *lexer) stateFn {
r := lx.next()
switch {
case isWhitespace(r) || isNL(r):
return lexSkip(lx, lexArrayValueEnd)
case r == commentStart:
lx.push(lexArrayValueEnd)
return lexCommentStart
case r == comma:
lx.ignore()
return lexArrayValue // move on to the next value
case r == arrayEnd:
return lexArrayEnd
}
return lx.errorf(
"expected a comma or array terminator %q, but got %q instead",
arrayEnd, r,
)
}
// lexArrayEnd finishes the lexing of an array.
// It assumes that a ']' has just been consumed.
func lexArrayEnd(lx *lexer) stateFn {
lx.ignore()
lx.emit(itemArrayEnd)
return lx.pop()
}
// lexInlineTableValue consumes one key/value pair in an inline table.
// It assumes that '{' or ',' have already been consumed. Whitespace is ignored.
func lexInlineTableValue(lx *lexer) stateFn {
r := lx.next()
switch {
case isWhitespace(r):
return lexSkip(lx, lexInlineTableValue)
case isNL(r):
return lx.errorf("newlines not allowed within inline tables")
case r == commentStart:
lx.push(lexInlineTableValue)
return lexCommentStart
case r == comma:
return lx.errorf("unexpected comma")
case r == inlineTableEnd:
return lexInlineTableEnd
}
lx.backup()
lx.push(lexInlineTableValueEnd)
return lexKeyStart
}
// lexInlineTableValueEnd consumes everything between the end of an inline table
// key/value pair and the next pair (or the end of the table):
// it ignores whitespace and expects either a ',' or a '}'.
func lexInlineTableValueEnd(lx *lexer) stateFn {
r := lx.next()
switch {
case isWhitespace(r):
return lexSkip(lx, lexInlineTableValueEnd)
case isNL(r):
return lx.errorf("newlines not allowed within inline tables")
case r == commentStart:
lx.push(lexInlineTableValueEnd)
return lexCommentStart
case r == comma:
lx.ignore()
return lexInlineTableValue
case r == inlineTableEnd:
return lexInlineTableEnd
}
return lx.errorf("expected a comma or an inline table terminator %q, "+
"but got %q instead", inlineTableEnd, r)
}
// lexInlineTableEnd finishes the lexing of an inline table.
// It assumes that a '}' has just been consumed.
func lexInlineTableEnd(lx *lexer) stateFn {
lx.ignore()
lx.emit(itemInlineTableEnd)
return lx.pop()
}
// lexString consumes the inner contents of a string. It assumes that the
// beginning '"' has already been consumed and ignored.
func lexString(lx *lexer) stateFn {
r := lx.next()
switch {
case r == eof:
return lx.errorf("unexpected EOF")
case isNL(r):
return lx.errorf("strings cannot contain newlines")
case r == '\\':
lx.push(lexString)
return lexStringEscape
case r == stringEnd:
lx.backup()
lx.emit(itemString)
lx.next()
lx.ignore()
return lx.pop()
}
return lexString
}
// lexMultilineString consumes the inner contents of a string. It assumes that
// the beginning '"""' has already been consumed and ignored.
func lexMultilineString(lx *lexer) stateFn {
switch lx.next() {
case eof:
return lx.errorf("unexpected EOF")
case '\\':
return lexMultilineStringEscape
case stringEnd:
if lx.accept(stringEnd) {
if lx.accept(stringEnd) {
lx.backup()
lx.backup()
lx.backup()
lx.emit(itemMultilineString)
lx.next()
lx.next()
lx.next()
lx.ignore()
return lx.pop()
}
lx.backup()
}
}
return lexMultilineString
}
// lexRawString consumes a raw string. Nothing can be escaped in such a string.
// It assumes that the beginning "'" has already been consumed and ignored.
func lexRawString(lx *lexer) stateFn {
r := lx.next()
switch {
case r == eof:
return lx.errorf("unexpected EOF")
case isNL(r):
return lx.errorf("strings cannot contain newlines")
case r == rawStringEnd:
lx.backup()
lx.emit(itemRawString)
lx.next()
lx.ignore()
return lx.pop()
}
return lexRawString
}
// lexMultilineRawString consumes a raw string. Nothing can be escaped in such
// a string. It assumes that the beginning "'''" has already been consumed and
// ignored.
func lexMultilineRawString(lx *lexer) stateFn {
switch lx.next() {
case eof:
return lx.errorf("unexpected EOF")
case rawStringEnd:
if lx.accept(rawStringEnd) {
if lx.accept(rawStringEnd) {
lx.backup()
lx.backup()
lx.backup()
lx.emit(itemRawMultilineString)
lx.next()
lx.next()
lx.next()
lx.ignore()
return lx.pop()
}
lx.backup()
}
}
return lexMultilineRawString
}
// lexMultilineStringEscape consumes an escaped character. It assumes that the
// preceding '\\' has already been consumed.
func lexMultilineStringEscape(lx *lexer) stateFn {
// Handle the special case first:
if isNL(lx.next()) {
return lexMultilineString
}
lx.backup()
lx.push(lexMultilineString)
return lexStringEscape(lx)
}
func lexStringEscape(lx *lexer) stateFn {
r := lx.next()
switch r {
case 'b':
fallthrough
case 't':
fallthrough
case 'n':
fallthrough
case 'f':
fallthrough
case 'r':
fallthrough
case '"':
fallthrough
case '\\':
return lx.pop()
case 'u':
return lexShortUnicodeEscape
case 'U':
return lexLongUnicodeEscape
}
return lx.errorf("invalid escape character %q; only the following "+
"escape characters are allowed: "+
`\b, \t, \n, \f, \r, \", \\, \uXXXX, and \UXXXXXXXX`, r)
}
func lexShortUnicodeEscape(lx *lexer) stateFn {
var r rune
for i := 0; i < 4; i++ {
r = lx.next()
if !isHexadecimal(r) {
return lx.errorf(`expected four hexadecimal digits after '\u', `+
"but got %q instead", lx.current())
}
}
return lx.pop()
}
func lexLongUnicodeEscape(lx *lexer) stateFn {
var r rune
for i := 0; i < 8; i++ {
r = lx.next()
if !isHexadecimal(r) {
return lx.errorf(`expected eight hexadecimal digits after '\U', `+
"but got %q instead", lx.current())
}
}
return lx.pop()
}
// lexNumberOrDateStart consumes either an integer, a float, or datetime.
func lexNumberOrDateStart(lx *lexer) stateFn {
r := lx.next()
if isDigit(r) {
return lexNumberOrDate
}
switch r {
case '_':
return lexNumber
case 'e', 'E':
return lexFloat
case '.':
return lx.errorf("floats must start with a digit, not '.'")
}
return lx.errorf("expected a digit but got %q", r)
}
// lexNumberOrDate consumes either an integer, float or datetime.
func lexNumberOrDate(lx *lexer) stateFn {
r := lx.next()
if isDigit(r) {
return lexNumberOrDate
}
switch r {
case '-':
return lexDatetime
case '_':
return lexNumber
case '.', 'e', 'E':
return lexFloat
}
lx.backup()
lx.emit(itemInteger)
return lx.pop()
}
// lexDatetime consumes a Datetime, to a first approximation.
// The parser validates that it matches one of the accepted formats.
func lexDatetime(lx *lexer) stateFn {
r := lx.next()
if isDigit(r) {
return lexDatetime
}
switch r {
case '-', 'T', ':', '.', 'Z', '+':
return lexDatetime
}
lx.backup()
lx.emit(itemDatetime)
return lx.pop()
}
// lexNumberStart consumes either an integer or a float. It assumes that a sign
// has already been read, but that *no* digits have been consumed.
// lexNumberStart will move to the appropriate integer or float states.
func lexNumberStart(lx *lexer) stateFn {
// We MUST see a digit. Even floats have to start with a digit.
r := lx.next()
if !isDigit(r) {
if r == '.' {
return lx.errorf("floats must start with a digit, not '.'")
}
return lx.errorf("expected a digit but got %q", r)
}
return lexNumber
}
// lexNumber consumes an integer or a float after seeing the first digit.
func lexNumber(lx *lexer) stateFn {
r := lx.next()
if isDigit(r) {
return lexNumber
}
switch r {
case '_':
return lexNumber
case '.', 'e', 'E':
return lexFloat
}
lx.backup()
lx.emit(itemInteger)
return lx.pop()
}
// lexFloat consumes the elements of a float. It allows any sequence of
// float-like characters, so floats emitted by the lexer are only a first
// approximation and must be validated by the parser.
func lexFloat(lx *lexer) stateFn {
r := lx.next()
if isDigit(r) {
return lexFloat
}
switch r {
case '_', '.', '-', '+', 'e', 'E':
return lexFloat
}
lx.backup()
lx.emit(itemFloat)
return lx.pop()
}
// lexBool consumes a bool string: 'true' or 'false.
func lexBool(lx *lexer) stateFn {
var rs []rune
for {
r := lx.next()
if !unicode.IsLetter(r) {
lx.backup()
break
}
rs = append(rs, r)
}
s := string(rs)
switch s {
case "true", "false":
lx.emit(itemBool)
return lx.pop()
}
return lx.errorf("expected value but found %q instead", s)
}
// lexCommentStart begins the lexing of a comment. It will emit
// itemCommentStart and consume no characters, passing control to lexComment.
func lexCommentStart(lx *lexer) stateFn {
lx.ignore()
lx.emit(itemCommentStart)
return lexComment
}
// lexComment lexes an entire comment. It assumes that '#' has been consumed.
// It will consume *up to* the first newline character, and pass control
// back to the last state on the stack.
func lexComment(lx *lexer) stateFn {
r := lx.peek()
if isNL(r) || r == eof {
lx.emit(itemText)
return lx.pop()
}
lx.next()
return lexComment
}
// lexSkip ignores all slurped input and moves on to the next state.
func lexSkip(lx *lexer, nextState stateFn) stateFn {
return func(lx *lexer) stateFn {
lx.ignore()
return nextState
}
}
// isWhitespace returns true if `r` is a whitespace character according
// to the spec.
func isWhitespace(r rune) bool {
return r == '\t' || r == ' '
}
func isNL(r rune) bool {
return r == '\n' || r == '\r'
}
func isDigit(r rune) bool {
return r >= '0' && r <= '9'
}
func isHexadecimal(r rune) bool {
return (r >= '0' && r <= '9') ||
(r >= 'a' && r <= 'f') ||
(r >= 'A' && r <= 'F')
}
func isBareKeyChar(r rune) bool {
return (r >= 'A' && r <= 'Z') ||
(r >= 'a' && r <= 'z') ||
(r >= '0' && r <= '9') ||
r == '_' ||
r == '-'
}
func (itype itemType) String() string {
switch itype {
case itemError:
return "Error"
case itemNIL:
return "NIL"
case itemEOF:
return "EOF"
case itemText:
return "Text"
case itemString, itemRawString, itemMultilineString, itemRawMultilineString:
return "String"
case itemBool:
return "Bool"
case itemInteger:
return "Integer"
case itemFloat:
return "Float"
case itemDatetime:
return "DateTime"
case itemTableStart:
return "TableStart"
case itemTableEnd:
return "TableEnd"
case itemKeyStart:
return "KeyStart"
case itemArray:
return "Array"
case itemArrayEnd:
return "ArrayEnd"
case itemCommentStart:
return "CommentStart"
}
panic(fmt.Sprintf("BUG: Unknown type '%d'.", int(itype)))
}
func (item item) String() string {
return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val)
}

View File

@@ -1,592 +0,0 @@
package toml
import (
"fmt"
"strconv"
"strings"
"time"
"unicode"
"unicode/utf8"
)
type parser struct {
mapping map[string]interface{}
types map[string]tomlType
lx *lexer
// A list of keys in the order that they appear in the TOML data.
ordered []Key
// the full key for the current hash in scope
context Key
// the base key name for everything except hashes
currentKey string
// rough approximation of line number
approxLine int
// A map of 'key.group.names' to whether they were created implicitly.
implicits map[string]bool
}
type parseError string
func (pe parseError) Error() string {
return string(pe)
}
func parse(data string) (p *parser, err error) {
defer func() {
if r := recover(); r != nil {
var ok bool
if err, ok = r.(parseError); ok {
return
}
panic(r)
}
}()
p = &parser{
mapping: make(map[string]interface{}),
types: make(map[string]tomlType),
lx: lex(data),
ordered: make([]Key, 0),
implicits: make(map[string]bool),
}
for {
item := p.next()
if item.typ == itemEOF {
break
}
p.topLevel(item)
}
return p, nil
}
func (p *parser) panicf(format string, v ...interface{}) {
msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s",
p.approxLine, p.current(), fmt.Sprintf(format, v...))
panic(parseError(msg))
}
func (p *parser) next() item {
it := p.lx.nextItem()
if it.typ == itemError {
p.panicf("%s", it.val)
}
return it
}
func (p *parser) bug(format string, v ...interface{}) {
panic(fmt.Sprintf("BUG: "+format+"\n\n", v...))
}
func (p *parser) expect(typ itemType) item {
it := p.next()
p.assertEqual(typ, it.typ)
return it
}
func (p *parser) assertEqual(expected, got itemType) {
if expected != got {
p.bug("Expected '%s' but got '%s'.", expected, got)
}
}
func (p *parser) topLevel(item item) {
switch item.typ {
case itemCommentStart:
p.approxLine = item.line
p.expect(itemText)
case itemTableStart:
kg := p.next()
p.approxLine = kg.line
var key Key
for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() {
key = append(key, p.keyString(kg))
}
p.assertEqual(itemTableEnd, kg.typ)
p.establishContext(key, false)
p.setType("", tomlHash)
p.ordered = append(p.ordered, key)
case itemArrayTableStart:
kg := p.next()
p.approxLine = kg.line
var key Key
for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() {
key = append(key, p.keyString(kg))
}
p.assertEqual(itemArrayTableEnd, kg.typ)
p.establishContext(key, true)
p.setType("", tomlArrayHash)
p.ordered = append(p.ordered, key)
case itemKeyStart:
kname := p.next()
p.approxLine = kname.line
p.currentKey = p.keyString(kname)
val, typ := p.value(p.next())
p.setValue(p.currentKey, val)
p.setType(p.currentKey, typ)
p.ordered = append(p.ordered, p.context.add(p.currentKey))
p.currentKey = ""
default:
p.bug("Unexpected type at top level: %s", item.typ)
}
}
// Gets a string for a key (or part of a key in a table name).
func (p *parser) keyString(it item) string {
switch it.typ {
case itemText:
return it.val
case itemString, itemMultilineString,
itemRawString, itemRawMultilineString:
s, _ := p.value(it)
return s.(string)
default:
p.bug("Unexpected key type: %s", it.typ)
panic("unreachable")
}
}
// value translates an expected value from the lexer into a Go value wrapped
// as an empty interface.
func (p *parser) value(it item) (interface{}, tomlType) {
switch it.typ {
case itemString:
return p.replaceEscapes(it.val), p.typeOfPrimitive(it)
case itemMultilineString:
trimmed := stripFirstNewline(stripEscapedWhitespace(it.val))
return p.replaceEscapes(trimmed), p.typeOfPrimitive(it)
case itemRawString:
return it.val, p.typeOfPrimitive(it)
case itemRawMultilineString:
return stripFirstNewline(it.val), p.typeOfPrimitive(it)
case itemBool:
switch it.val {
case "true":
return true, p.typeOfPrimitive(it)
case "false":
return false, p.typeOfPrimitive(it)
}
p.bug("Expected boolean value, but got '%s'.", it.val)
case itemInteger:
if !numUnderscoresOK(it.val) {
p.panicf("Invalid integer %q: underscores must be surrounded by digits",
it.val)
}
val := strings.Replace(it.val, "_", "", -1)
num, err := strconv.ParseInt(val, 10, 64)
if err != nil {
// Distinguish integer values. Normally, it'd be a bug if the lexer
// provides an invalid integer, but it's possible that the number is
// out of range of valid values (which the lexer cannot determine).
// So mark the former as a bug but the latter as a legitimate user
// error.
if e, ok := err.(*strconv.NumError); ok &&
e.Err == strconv.ErrRange {
p.panicf("Integer '%s' is out of the range of 64-bit "+
"signed integers.", it.val)
} else {
p.bug("Expected integer value, but got '%s'.", it.val)
}
}
return num, p.typeOfPrimitive(it)
case itemFloat:
parts := strings.FieldsFunc(it.val, func(r rune) bool {
switch r {
case '.', 'e', 'E':
return true
}
return false
})
for _, part := range parts {
if !numUnderscoresOK(part) {
p.panicf("Invalid float %q: underscores must be "+
"surrounded by digits", it.val)
}
}
if !numPeriodsOK(it.val) {
// As a special case, numbers like '123.' or '1.e2',
// which are valid as far as Go/strconv are concerned,
// must be rejected because TOML says that a fractional
// part consists of '.' followed by 1+ digits.
p.panicf("Invalid float %q: '.' must be followed "+
"by one or more digits", it.val)
}
val := strings.Replace(it.val, "_", "", -1)
num, err := strconv.ParseFloat(val, 64)
if err != nil {
if e, ok := err.(*strconv.NumError); ok &&
e.Err == strconv.ErrRange {
p.panicf("Float '%s' is out of the range of 64-bit "+
"IEEE-754 floating-point numbers.", it.val)
} else {
p.panicf("Invalid float value: %q", it.val)
}
}
return num, p.typeOfPrimitive(it)
case itemDatetime:
var t time.Time
var ok bool
var err error
for _, format := range []string{
"2006-01-02T15:04:05Z07:00",
"2006-01-02T15:04:05",
"2006-01-02",
} {
t, err = time.ParseInLocation(format, it.val, time.Local)
if err == nil {
ok = true
break
}
}
if !ok {
p.panicf("Invalid TOML Datetime: %q.", it.val)
}
return t, p.typeOfPrimitive(it)
case itemArray:
array := make([]interface{}, 0)
types := make([]tomlType, 0)
for it = p.next(); it.typ != itemArrayEnd; it = p.next() {
if it.typ == itemCommentStart {
p.expect(itemText)
continue
}
val, typ := p.value(it)
array = append(array, val)
types = append(types, typ)
}
return array, p.typeOfArray(types)
case itemInlineTableStart:
var (
hash = make(map[string]interface{})
outerContext = p.context
outerKey = p.currentKey
)
p.context = append(p.context, p.currentKey)
p.currentKey = ""
for it := p.next(); it.typ != itemInlineTableEnd; it = p.next() {
if it.typ != itemKeyStart {
p.bug("Expected key start but instead found %q, around line %d",
it.val, p.approxLine)
}
if it.typ == itemCommentStart {
p.expect(itemText)
continue
}
// retrieve key
k := p.next()
p.approxLine = k.line
kname := p.keyString(k)
// retrieve value
p.currentKey = kname
val, typ := p.value(p.next())
// make sure we keep metadata up to date
p.setType(kname, typ)
p.ordered = append(p.ordered, p.context.add(p.currentKey))
hash[kname] = val
}
p.context = outerContext
p.currentKey = outerKey
return hash, tomlHash
}
p.bug("Unexpected value type: %s", it.typ)
panic("unreachable")
}
// numUnderscoresOK checks whether each underscore in s is surrounded by
// characters that are not underscores.
func numUnderscoresOK(s string) bool {
accept := false
for _, r := range s {
if r == '_' {
if !accept {
return false
}
accept = false
continue
}
accept = true
}
return accept
}
// numPeriodsOK checks whether every period in s is followed by a digit.
func numPeriodsOK(s string) bool {
period := false
for _, r := range s {
if period && !isDigit(r) {
return false
}
period = r == '.'
}
return !period
}
// establishContext sets the current context of the parser,
// where the context is either a hash or an array of hashes. Which one is
// set depends on the value of the `array` parameter.
//
// Establishing the context also makes sure that the key isn't a duplicate, and
// will create implicit hashes automatically.
func (p *parser) establishContext(key Key, array bool) {
var ok bool
// Always start at the top level and drill down for our context.
hashContext := p.mapping
keyContext := make(Key, 0)
// We only need implicit hashes for key[0:-1]
for _, k := range key[0 : len(key)-1] {
_, ok = hashContext[k]
keyContext = append(keyContext, k)
// No key? Make an implicit hash and move on.
if !ok {
p.addImplicit(keyContext)
hashContext[k] = make(map[string]interface{})
}
// If the hash context is actually an array of tables, then set
// the hash context to the last element in that array.
//
// Otherwise, it better be a table, since this MUST be a key group (by
// virtue of it not being the last element in a key).
switch t := hashContext[k].(type) {
case []map[string]interface{}:
hashContext = t[len(t)-1]
case map[string]interface{}:
hashContext = t
default:
p.panicf("Key '%s' was already created as a hash.", keyContext)
}
}
p.context = keyContext
if array {
// If this is the first element for this array, then allocate a new
// list of tables for it.
k := key[len(key)-1]
if _, ok := hashContext[k]; !ok {
hashContext[k] = make([]map[string]interface{}, 0, 5)
}
// Add a new table. But make sure the key hasn't already been used
// for something else.
if hash, ok := hashContext[k].([]map[string]interface{}); ok {
hashContext[k] = append(hash, make(map[string]interface{}))
} else {
p.panicf("Key '%s' was already created and cannot be used as "+
"an array.", keyContext)
}
} else {
p.setValue(key[len(key)-1], make(map[string]interface{}))
}
p.context = append(p.context, key[len(key)-1])
}
// setValue sets the given key to the given value in the current context.
// It will make sure that the key hasn't already been defined, account for
// implicit key groups.
func (p *parser) setValue(key string, value interface{}) {
var tmpHash interface{}
var ok bool
hash := p.mapping
keyContext := make(Key, 0)
for _, k := range p.context {
keyContext = append(keyContext, k)
if tmpHash, ok = hash[k]; !ok {
p.bug("Context for key '%s' has not been established.", keyContext)
}
switch t := tmpHash.(type) {
case []map[string]interface{}:
// The context is a table of hashes. Pick the most recent table
// defined as the current hash.
hash = t[len(t)-1]
case map[string]interface{}:
hash = t
default:
p.bug("Expected hash to have type 'map[string]interface{}', but "+
"it has '%T' instead.", tmpHash)
}
}
keyContext = append(keyContext, key)
if _, ok := hash[key]; ok {
// Typically, if the given key has already been set, then we have
// to raise an error since duplicate keys are disallowed. However,
// it's possible that a key was previously defined implicitly. In this
// case, it is allowed to be redefined concretely. (See the
// `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.)
//
// But we have to make sure to stop marking it as an implicit. (So that
// another redefinition provokes an error.)
//
// Note that since it has already been defined (as a hash), we don't
// want to overwrite it. So our business is done.
if p.isImplicit(keyContext) {
p.removeImplicit(keyContext)
return
}
// Otherwise, we have a concrete key trying to override a previous
// key, which is *always* wrong.
p.panicf("Key '%s' has already been defined.", keyContext)
}
hash[key] = value
}
// setType sets the type of a particular value at a given key.
// It should be called immediately AFTER setValue.
//
// Note that if `key` is empty, then the type given will be applied to the
// current context (which is either a table or an array of tables).
func (p *parser) setType(key string, typ tomlType) {
keyContext := make(Key, 0, len(p.context)+1)
for _, k := range p.context {
keyContext = append(keyContext, k)
}
if len(key) > 0 { // allow type setting for hashes
keyContext = append(keyContext, key)
}
p.types[keyContext.String()] = typ
}
// addImplicit sets the given Key as having been created implicitly.
func (p *parser) addImplicit(key Key) {
p.implicits[key.String()] = true
}
// removeImplicit stops tagging the given key as having been implicitly
// created.
func (p *parser) removeImplicit(key Key) {
p.implicits[key.String()] = false
}
// isImplicit returns true if the key group pointed to by the key was created
// implicitly.
func (p *parser) isImplicit(key Key) bool {
return p.implicits[key.String()]
}
// current returns the full key name of the current context.
func (p *parser) current() string {
if len(p.currentKey) == 0 {
return p.context.String()
}
if len(p.context) == 0 {
return p.currentKey
}
return fmt.Sprintf("%s.%s", p.context, p.currentKey)
}
func stripFirstNewline(s string) string {
if len(s) == 0 || s[0] != '\n' {
return s
}
return s[1:]
}
func stripEscapedWhitespace(s string) string {
esc := strings.Split(s, "\\\n")
if len(esc) > 1 {
for i := 1; i < len(esc); i++ {
esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace)
}
}
return strings.Join(esc, "")
}
func (p *parser) replaceEscapes(str string) string {
var replaced []rune
s := []byte(str)
r := 0
for r < len(s) {
if s[r] != '\\' {
c, size := utf8.DecodeRune(s[r:])
r += size
replaced = append(replaced, c)
continue
}
r += 1
if r >= len(s) {
p.bug("Escape sequence at end of string.")
return ""
}
switch s[r] {
default:
p.bug("Expected valid escape code after \\, but got %q.", s[r])
return ""
case 'b':
replaced = append(replaced, rune(0x0008))
r += 1
case 't':
replaced = append(replaced, rune(0x0009))
r += 1
case 'n':
replaced = append(replaced, rune(0x000A))
r += 1
case 'f':
replaced = append(replaced, rune(0x000C))
r += 1
case 'r':
replaced = append(replaced, rune(0x000D))
r += 1
case '"':
replaced = append(replaced, rune(0x0022))
r += 1
case '\\':
replaced = append(replaced, rune(0x005C))
r += 1
case 'u':
// At this point, we know we have a Unicode escape of the form
// `uXXXX` at [r, r+5). (Because the lexer guarantees this
// for us.)
escaped := p.asciiEscapeToUnicode(s[r+1 : r+5])
replaced = append(replaced, escaped)
r += 5
case 'U':
// At this point, we know we have a Unicode escape of the form
// `uXXXX` at [r, r+9). (Because the lexer guarantees this
// for us.)
escaped := p.asciiEscapeToUnicode(s[r+1 : r+9])
replaced = append(replaced, escaped)
r += 9
}
}
return string(replaced)
}
func (p *parser) asciiEscapeToUnicode(bs []byte) rune {
s := string(bs)
hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32)
if err != nil {
p.bug("Could not parse '%s' as a hexadecimal number, but the "+
"lexer claims it's OK: %s", s, err)
}
if !utf8.ValidRune(rune(hex)) {
p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s)
}
return rune(hex)
}
func isStringType(ty itemType) bool {
return ty == itemString || ty == itemMultilineString ||
ty == itemRawString || ty == itemRawMultilineString
}

View File

@@ -1 +0,0 @@
au BufWritePost *.go silent!make tags > /dev/null 2>&1

View File

@@ -1,91 +0,0 @@
package toml
// tomlType represents any Go type that corresponds to a TOML type.
// While the first draft of the TOML spec has a simplistic type system that
// probably doesn't need this level of sophistication, we seem to be militating
// toward adding real composite types.
type tomlType interface {
typeString() string
}
// typeEqual accepts any two types and returns true if they are equal.
func typeEqual(t1, t2 tomlType) bool {
if t1 == nil || t2 == nil {
return false
}
return t1.typeString() == t2.typeString()
}
func typeIsHash(t tomlType) bool {
return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash)
}
type tomlBaseType string
func (btype tomlBaseType) typeString() string {
return string(btype)
}
func (btype tomlBaseType) String() string {
return btype.typeString()
}
var (
tomlInteger tomlBaseType = "Integer"
tomlFloat tomlBaseType = "Float"
tomlDatetime tomlBaseType = "Datetime"
tomlString tomlBaseType = "String"
tomlBool tomlBaseType = "Bool"
tomlArray tomlBaseType = "Array"
tomlHash tomlBaseType = "Hash"
tomlArrayHash tomlBaseType = "ArrayHash"
)
// typeOfPrimitive returns a tomlType of any primitive value in TOML.
// Primitive values are: Integer, Float, Datetime, String and Bool.
//
// Passing a lexer item other than the following will cause a BUG message
// to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime.
func (p *parser) typeOfPrimitive(lexItem item) tomlType {
switch lexItem.typ {
case itemInteger:
return tomlInteger
case itemFloat:
return tomlFloat
case itemDatetime:
return tomlDatetime
case itemString:
return tomlString
case itemMultilineString:
return tomlString
case itemRawString:
return tomlString
case itemRawMultilineString:
return tomlString
case itemBool:
return tomlBool
}
p.bug("Cannot infer primitive type of lex item '%s'.", lexItem)
panic("unreachable")
}
// typeOfArray returns a tomlType for an array given a list of types of its
// values.
//
// In the current spec, if an array is homogeneous, then its type is always
// "Array". If the array is not homogeneous, an error is generated.
func (p *parser) typeOfArray(types []tomlType) tomlType {
// Empty arrays are cool.
if len(types) == 0 {
return tomlArray
}
theType := types[0]
for _, t := range types[1:] {
if !typeEqual(theType, t) {
p.panicf("Array contains values of type '%s' and '%s', but "+
"arrays must be homogeneous.", theType, t)
}
}
return tomlArray
}

View File

@@ -1,242 +0,0 @@
package toml
// Struct field handling is adapted from code in encoding/json:
//
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the Go distribution.
import (
"reflect"
"sort"
"sync"
)
// A field represents a single field found in a struct.
type field struct {
name string // the name of the field (`toml` tag included)
tag bool // whether field has a `toml` tag
index []int // represents the depth of an anonymous field
typ reflect.Type // the type of the field
}
// byName sorts field by name, breaking ties with depth,
// then breaking ties with "name came from toml tag", then
// breaking ties with index sequence.
type byName []field
func (x byName) Len() int { return len(x) }
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byName) Less(i, j int) bool {
if x[i].name != x[j].name {
return x[i].name < x[j].name
}
if len(x[i].index) != len(x[j].index) {
return len(x[i].index) < len(x[j].index)
}
if x[i].tag != x[j].tag {
return x[i].tag
}
return byIndex(x).Less(i, j)
}
// byIndex sorts field by index sequence.
type byIndex []field
func (x byIndex) Len() int { return len(x) }
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
func (x byIndex) Less(i, j int) bool {
for k, xik := range x[i].index {
if k >= len(x[j].index) {
return false
}
if xik != x[j].index[k] {
return xik < x[j].index[k]
}
}
return len(x[i].index) < len(x[j].index)
}
// typeFields returns a list of fields that TOML should recognize for the given
// type. The algorithm is breadth-first search over the set of structs to
// include - the top struct and then any reachable anonymous structs.
func typeFields(t reflect.Type) []field {
// Anonymous fields to explore at the current level and the next.
current := []field{}
next := []field{{typ: t}}
// Count of queued names for current level and the next.
count := map[reflect.Type]int{}
nextCount := map[reflect.Type]int{}
// Types already visited at an earlier level.
visited := map[reflect.Type]bool{}
// Fields found.
var fields []field
for len(next) > 0 {
current, next = next, current[:0]
count, nextCount = nextCount, map[reflect.Type]int{}
for _, f := range current {
if visited[f.typ] {
continue
}
visited[f.typ] = true
// Scan f.typ for fields to include.
for i := 0; i < f.typ.NumField(); i++ {
sf := f.typ.Field(i)
if sf.PkgPath != "" && !sf.Anonymous { // unexported
continue
}
opts := getOptions(sf.Tag)
if opts.skip {
continue
}
index := make([]int, len(f.index)+1)
copy(index, f.index)
index[len(f.index)] = i
ft := sf.Type
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
// Follow pointer.
ft = ft.Elem()
}
// Record found field and index sequence.
if opts.name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
tagged := opts.name != ""
name := opts.name
if name == "" {
name = sf.Name
}
fields = append(fields, field{name, tagged, index, ft})
if count[f.typ] > 1 {
// If there were multiple instances, add a second,
// so that the annihilation code will see a duplicate.
// It only cares about the distinction between 1 or 2,
// so don't bother generating any more copies.
fields = append(fields, fields[len(fields)-1])
}
continue
}
// Record new anonymous struct to explore in next round.
nextCount[ft]++
if nextCount[ft] == 1 {
f := field{name: ft.Name(), index: index, typ: ft}
next = append(next, f)
}
}
}
}
sort.Sort(byName(fields))
// Delete all fields that are hidden by the Go rules for embedded fields,
// except that fields with TOML tags are promoted.
// The fields are sorted in primary order of name, secondary order
// of field index length. Loop over names; for each name, delete
// hidden fields by choosing the one dominant field that survives.
out := fields[:0]
for advance, i := 0, 0; i < len(fields); i += advance {
// One iteration per name.
// Find the sequence of fields with the name of this first field.
fi := fields[i]
name := fi.name
for advance = 1; i+advance < len(fields); advance++ {
fj := fields[i+advance]
if fj.name != name {
break
}
}
if advance == 1 { // Only one field with this name
out = append(out, fi)
continue
}
dominant, ok := dominantField(fields[i : i+advance])
if ok {
out = append(out, dominant)
}
}
fields = out
sort.Sort(byIndex(fields))
return fields
}
// dominantField looks through the fields, all of which are known to
// have the same name, to find the single field that dominates the
// others using Go's embedding rules, modified by the presence of
// TOML tags. If there are multiple top-level fields, the boolean
// will be false: This condition is an error in Go and we skip all
// the fields.
func dominantField(fields []field) (field, bool) {
// The fields are sorted in increasing index-length order. The winner
// must therefore be one with the shortest index length. Drop all
// longer entries, which is easy: just truncate the slice.
length := len(fields[0].index)
tagged := -1 // Index of first tagged field.
for i, f := range fields {
if len(f.index) > length {
fields = fields[:i]
break
}
if f.tag {
if tagged >= 0 {
// Multiple tagged fields at the same level: conflict.
// Return no field.
return field{}, false
}
tagged = i
}
}
if tagged >= 0 {
return fields[tagged], true
}
// All remaining fields have the same length. If there's more than one,
// we have a conflict (two fields named "X" at the same level) and we
// return no field.
if len(fields) > 1 {
return field{}, false
}
return fields[0], true
}
var fieldCache struct {
sync.RWMutex
m map[reflect.Type][]field
}
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
func cachedTypeFields(t reflect.Type) []field {
fieldCache.RLock()
f := fieldCache.m[t]
fieldCache.RUnlock()
if f != nil {
return f
}
// Compute fields without lock.
// Might duplicate effort but won't hold other computations back.
f = typeFields(t)
if f == nil {
f = []field{}
}
fieldCache.Lock()
if fieldCache.m == nil {
fieldCache.m = map[reflect.Type][]field{}
}
fieldCache.m[t] = f
fieldCache.Unlock()
return f
}

View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2017 VividCortex
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -1,18 +0,0 @@
mysqlerr
========
MySQL Server Error Constants
Covers up to MySQL 5.7.13. Notice that some constants were renamed in later
versions of MySQL, because they became obsolete. (In case you wonder: the names
here match the symbols MySQL uses in source code.) Obsolete names haven't been
changed in this package to avoid breaking code, but you should no longer be
using them in applications. Here's the full list of changes since this package's
first version:
| Code | This package | MySQL (as of 5.7.8) |
| ---: | ------------ | ------------------- |
| 1150 | ER_DELAYED_CANT_CHANGE_LOCK | ER_UNUSED1 |
| 1151 | ER_TOO_MANY_DELAYED_THREADS | ER_UNUSED2 |
| 1165 | ER_DELAYED_INSERT_TABLE_LOCKED | ER_UNUSED3 |
| 1349 | ER_VIEW_SELECT_DERIVED | ER_VIEW_SELECT_DERIVED_UNUSED |

File diff suppressed because it is too large Load Diff

View File

@@ -1,35 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
### Go template
# Binaries for programs and plugins
*.exe
*.dll
*.so
*.dylib
*.o
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/
bin/
vendor/

View File

@@ -1,44 +0,0 @@
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
[[projects]]
digest = "1:56c130d885a4aacae1dd9c7b71cfe39912c7ebc1ff7d2b46083c8812996dc43b"
name = "github.com/davecgh/go-spew"
packages = ["spew"]
pruneopts = ""
revision = "346938d642f2ec3594ed81d874461961cd0faa76"
version = "v1.1.0"
[[projects]]
digest = "1:1d7e1867c49a6dd9856598ef7c3123604ea3daabf5b83f303ff457bcbc410b1d"
name = "github.com/pkg/errors"
packages = ["."]
pruneopts = ""
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
version = "v0.8.1"
[[projects]]
digest = "1:256484dbbcd271f9ecebc6795b2df8cad4c458dd0f5fd82a8c2fa0c29f233411"
name = "github.com/pmezard/go-difflib"
packages = ["difflib"]
pruneopts = ""
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
version = "v1.0.0"
[[projects]]
digest = "1:2d0dc026c4aef5e2f3a0e06a4dabe268b840d8f63190cf6894e02134a03f52c5"
name = "github.com/stretchr/testify"
packages = ["assert"]
pruneopts = ""
revision = "b91bfb9ebec76498946beb6af7c0230c7cc7ba6c"
version = "v1.2.0"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
input-imports = [
"github.com/pkg/errors",
"github.com/stretchr/testify/assert",
]
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -1,23 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[[constraint]]
name = "github.com/stretchr/testify"
version = "1.2.0"
[[constraint]]
name = "github.com/pkg/errors"
version = "0.8.1"

View File

@@ -1,54 +0,0 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
GO_BUILD=go build
GO_GEN=go generate
GO_TEST?=go test
GOPATH=$(realpath ../../../../../..)
GO_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -not -name '*_test.go')
ALL_SOURCES := $(shell find . -path ./_lib -prune -o -name '*.go' -name '*.s' -not -name '*_test.go')
SOURCES_NO_VENDOR := $(shell find . -path ./vendor -prune -o -name "*.go" -not -name '*_test.go' -print)
.PHONEY: test bench assembly generate
assembly:
@$(MAKE) -C memory assembly
@$(MAKE) -C math assembly
generate: bin/tmpl
bin/tmpl -i -data=numeric.tmpldata type_traits_numeric.gen.go.tmpl type_traits_numeric.gen_test.go.tmpl array/numeric.gen.go.tmpl array/numericbuilder.gen_test.go.tmpl array/numericbuilder.gen.go.tmpl array/bufferbuilder_numeric.gen.go.tmpl
bin/tmpl -i -data=datatype_numeric.gen.go.tmpldata datatype_numeric.gen.go.tmpl
@$(MAKE) -C math generate
fmt: $(SOURCES_NO_VENDOR)
goimports -w $^
bench: $(GO_SOURCES) | assembly
$(GO_TEST) $(GO_TEST_ARGS) -bench=. -run=- ./...
bench-noasm: $(GO_SOURCES)
$(GO_TEST) $(GO_TEST_ARGS) -tags='noasm' -bench=. -run=- ./...
test: $(GO_SOURCES) | assembly
$(GO_TEST) $(GO_TEST_ARGS) ./...
test-noasm: $(GO_SOURCES)
$(GO_TEST) $(GO_TEST_ARGS) -tags='noasm' ./...
bin/tmpl: _tools/tmpl/main.go
$(GO_BUILD) -o $@ ./_tools/tmpl

View File

@@ -1,206 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array // import "github.com/apache/arrow/go/arrow/array"
import (
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
)
// A type which satisfies array.Interface represents an immutable sequence of values.
type Interface interface {
// DataType returns the type metadata for this instance.
DataType() arrow.DataType
// NullN returns the number of null values in the array.
NullN() int
// NullBitmapBytes returns a byte slice of the validity bitmap.
NullBitmapBytes() []byte
// IsNull returns true if value at index is null.
// NOTE: IsNull will panic if NullBitmapBytes is not empty and 0 > i ≥ Len.
IsNull(i int) bool
// IsValid returns true if value at index is not null.
// NOTE: IsValid will panic if NullBitmapBytes is not empty and 0 > i ≥ Len.
IsValid(i int) bool
Data() *Data
// Len returns the number of elements in the array.
Len() int
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
Retain()
// Release decreases the reference count by 1.
// Release may be called simultaneously from multiple goroutines.
// When the reference count goes to zero, the memory is freed.
Release()
}
const (
// UnknownNullCount specifies the NullN should be calculated from the null bitmap buffer.
UnknownNullCount = -1
)
type array struct {
refCount int64
data *Data
nullBitmapBytes []byte
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (a *array) Retain() {
atomic.AddInt64(&a.refCount, 1)
}
// Release decreases the reference count by 1.
// Release may be called simultaneously from multiple goroutines.
// When the reference count goes to zero, the memory is freed.
func (a *array) Release() {
debug.Assert(atomic.LoadInt64(&a.refCount) > 0, "too many releases")
if atomic.AddInt64(&a.refCount, -1) == 0 {
a.data.Release()
a.data, a.nullBitmapBytes = nil, nil
}
}
// DataType returns the type metadata for this instance.
func (a *array) DataType() arrow.DataType { return a.data.dtype }
// NullN returns the number of null values in the array.
func (a *array) NullN() int {
if a.data.nulls < 0 {
a.data.nulls = a.data.length - bitutil.CountSetBits(a.nullBitmapBytes, a.data.offset, a.data.length)
}
return a.data.nulls
}
// NullBitmapBytes returns a byte slice of the validity bitmap.
func (a *array) NullBitmapBytes() []byte { return a.nullBitmapBytes }
func (a *array) Data() *Data { return a.data }
// Len returns the number of elements in the array.
func (a *array) Len() int { return a.data.length }
// IsNull returns true if value at index is null.
// NOTE: IsNull will panic if NullBitmapBytes is not empty and 0 > i ≥ Len.
func (a *array) IsNull(i int) bool {
return len(a.nullBitmapBytes) != 0 && bitutil.BitIsNotSet(a.nullBitmapBytes, a.data.offset+i)
}
// IsValid returns true if value at index is not null.
// NOTE: IsValid will panic if NullBitmapBytes is not empty and 0 > i ≥ Len.
func (a *array) IsValid(i int) bool {
return len(a.nullBitmapBytes) == 0 || bitutil.BitIsSet(a.nullBitmapBytes, a.data.offset+i)
}
func (a *array) setData(data *Data) {
if a.data != nil {
a.data.Release()
}
data.Retain()
if len(data.buffers) > 0 && data.buffers[0] != nil {
a.nullBitmapBytes = data.buffers[0].Bytes()
}
a.data = data
}
func (a *array) Offset() int {
return a.data.Offset()
}
type arrayConstructorFn func(*Data) Interface
var (
makeArrayFn [32]arrayConstructorFn
)
func unsupportedArrayType(data *Data) Interface {
panic("unsupported data type: " + data.dtype.ID().String())
}
func invalidDataType(data *Data) Interface {
panic("invalid data type: " + data.dtype.ID().String())
}
// MakeFromData constructs a strongly-typed array instance from generic Data.
func MakeFromData(data *Data) Interface {
return makeArrayFn[byte(data.dtype.ID()&0x1f)](data)
}
// NewSlice constructs a zero-copy slice of the array with the indicated
// indices i and j, corresponding to array[i:j].
// The returned array must be Release()'d after use.
//
// NewSlice panics if the slice is outside the valid range of the input array.
// NewSlice panics if j < i.
func NewSlice(arr Interface, i, j int64) Interface {
data := NewSliceData(arr.Data(), i, j)
slice := MakeFromData(data)
data.Release()
return slice
}
func init() {
makeArrayFn = [...]arrayConstructorFn{
arrow.NULL: func(data *Data) Interface { return NewNullData(data) },
arrow.BOOL: func(data *Data) Interface { return NewBooleanData(data) },
arrow.UINT8: func(data *Data) Interface { return NewUint8Data(data) },
arrow.INT8: func(data *Data) Interface { return NewInt8Data(data) },
arrow.UINT16: func(data *Data) Interface { return NewUint16Data(data) },
arrow.INT16: func(data *Data) Interface { return NewInt16Data(data) },
arrow.UINT32: func(data *Data) Interface { return NewUint32Data(data) },
arrow.INT32: func(data *Data) Interface { return NewInt32Data(data) },
arrow.UINT64: func(data *Data) Interface { return NewUint64Data(data) },
arrow.INT64: func(data *Data) Interface { return NewInt64Data(data) },
arrow.FLOAT16: func(data *Data) Interface { return NewFloat16Data(data) },
arrow.FLOAT32: func(data *Data) Interface { return NewFloat32Data(data) },
arrow.FLOAT64: func(data *Data) Interface { return NewFloat64Data(data) },
arrow.STRING: func(data *Data) Interface { return NewStringData(data) },
arrow.BINARY: func(data *Data) Interface { return NewBinaryData(data) },
arrow.FIXED_SIZE_BINARY: func(data *Data) Interface { return NewFixedSizeBinaryData(data) },
arrow.DATE32: func(data *Data) Interface { return NewDate32Data(data) },
arrow.DATE64: func(data *Data) Interface { return NewDate64Data(data) },
arrow.TIMESTAMP: func(data *Data) Interface { return NewTimestampData(data) },
arrow.TIME32: func(data *Data) Interface { return NewTime32Data(data) },
arrow.TIME64: func(data *Data) Interface { return NewTime64Data(data) },
arrow.INTERVAL: func(data *Data) Interface { return NewIntervalData(data) },
arrow.DECIMAL: func(data *Data) Interface { return NewDecimal128Data(data) },
arrow.LIST: func(data *Data) Interface { return NewListData(data) },
arrow.STRUCT: func(data *Data) Interface { return NewStructData(data) },
arrow.UNION: unsupportedArrayType,
arrow.DICTIONARY: unsupportedArrayType,
arrow.MAP: unsupportedArrayType,
arrow.EXTENSION: unsupportedArrayType,
arrow.FIXED_SIZE_LIST: func(data *Data) Interface { return NewFixedSizeListData(data) },
arrow.DURATION: func(data *Data) Interface { return NewDurationData(data) },
// invalid data types to fill out array size 2⁵-1
31: invalidDataType,
}
}

View File

@@ -1,134 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"bytes"
"fmt"
"strings"
"unsafe"
"github.com/apache/arrow/go/arrow"
)
// A type which represents an immutable sequence of variable-length binary strings.
type Binary struct {
array
valueOffsets []int32
valueBytes []byte
}
// NewBinaryData constructs a new Binary array from data.
func NewBinaryData(data *Data) *Binary {
a := &Binary{}
a.refCount = 1
a.setData(data)
return a
}
// Value returns the slice at index i. This value should not be mutated.
func (a *Binary) Value(i int) []byte {
if i < 0 || i >= a.array.data.length {
panic("arrow/array: index out of range")
}
idx := a.array.data.offset + i
return a.valueBytes[a.valueOffsets[idx]:a.valueOffsets[idx+1]]
}
// ValueString returns the string at index i without performing additional allocations.
// The string is only valid for the lifetime of the Binary array.
func (a *Binary) ValueString(i int) string {
b := a.Value(i)
return *(*string)(unsafe.Pointer(&b))
}
func (a *Binary) ValueOffset(i int) int {
if i < 0 || i >= a.array.data.length {
panic("arrow/array: index out of range")
}
return int(a.valueOffsets[a.array.data.offset+i])
}
func (a *Binary) ValueLen(i int) int {
if i < 0 || i >= a.array.data.length {
panic("arrow/array: index out of range")
}
beg := a.array.data.offset + i
return int(a.valueOffsets[beg+1] - a.valueOffsets[beg])
}
func (a *Binary) ValueOffsets() []int32 {
beg := a.array.data.offset
end := beg + a.array.data.length + 1
return a.valueOffsets[beg:end]
}
func (a *Binary) ValueBytes() []byte {
beg := a.array.data.offset
end := beg + a.array.data.length
return a.valueBytes[a.valueOffsets[beg]:a.valueOffsets[end]]
}
func (a *Binary) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i := 0; i < a.Len(); i++ {
if i > 0 {
o.WriteString(" ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%q", a.ValueString(i))
}
}
o.WriteString("]")
return o.String()
}
func (a *Binary) setData(data *Data) {
if len(data.buffers) != 3 {
panic("len(data.buffers) != 3")
}
a.array.setData(data)
if valueData := data.buffers[2]; valueData != nil {
a.valueBytes = valueData.Bytes()
}
if valueOffsets := data.buffers[1]; valueOffsets != nil {
a.valueOffsets = arrow.Int32Traits.CastFromBytes(valueOffsets.Bytes())
}
}
func arrayEqualBinary(left, right *Binary) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if bytes.Compare(left.Value(i), right.Value(i)) != 0 {
return false
}
}
return true
}
var (
_ Interface = (*Binary)(nil)
)

View File

@@ -1,217 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"math"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
const (
binaryArrayMaximumCapacity = math.MaxInt32
)
// A BinaryBuilder is used to build a Binary array using the Append methods.
type BinaryBuilder struct {
builder
dtype arrow.BinaryDataType
offsets *int32BufferBuilder
values *byteBufferBuilder
}
func NewBinaryBuilder(mem memory.Allocator, dtype arrow.BinaryDataType) *BinaryBuilder {
b := &BinaryBuilder{
builder: builder{refCount: 1, mem: mem},
dtype: dtype,
offsets: newInt32BufferBuilder(mem),
values: newByteBufferBuilder(mem),
}
return b
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (b *BinaryBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.offsets != nil {
b.offsets.Release()
b.offsets = nil
}
if b.values != nil {
b.values.Release()
b.values = nil
}
}
}
func (b *BinaryBuilder) Append(v []byte) {
b.Reserve(1)
b.appendNextOffset()
b.values.Append(v)
b.UnsafeAppendBoolToBitmap(true)
}
func (b *BinaryBuilder) AppendString(v string) {
b.Append([]byte(v))
}
func (b *BinaryBuilder) AppendNull() {
b.Reserve(1)
b.appendNextOffset()
b.UnsafeAppendBoolToBitmap(false)
}
// AppendValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *BinaryBuilder) AppendValues(v [][]byte, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
for _, vv := range v {
b.appendNextOffset()
b.values.Append(vv)
}
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
// AppendStringValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *BinaryBuilder) AppendStringValues(v []string, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
for _, vv := range v {
b.appendNextOffset()
b.values.Append([]byte(vv))
}
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
func (b *BinaryBuilder) Value(i int) []byte {
offsets := b.offsets.Values()
start := int(offsets[i])
var end int
if i == (b.length - 1) {
end = b.values.Len()
} else {
end = int(offsets[i+1])
}
return b.values.Bytes()[start:end]
}
func (b *BinaryBuilder) init(capacity int) {
b.builder.init(capacity)
b.offsets.resize((capacity + 1) * arrow.Int32SizeBytes)
}
// DataLen returns the number of bytes in the data array.
func (b *BinaryBuilder) DataLen() int { return b.values.length }
// DataCap returns the total number of bytes that can be stored
// without allocating additional memory.
func (b *BinaryBuilder) DataCap() int { return b.values.capacity }
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *BinaryBuilder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// ReserveData ensures there is enough space for appending n bytes
// by checking the capacity and resizing the data buffer if necessary.
func (b *BinaryBuilder) ReserveData(n int) {
if b.values.capacity < b.values.length+n {
b.values.resize(b.values.Len() + n)
}
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may be reduced.
func (b *BinaryBuilder) Resize(n int) {
b.offsets.resize((n + 1) * arrow.Int32SizeBytes)
b.builder.resize(n, b.init)
}
// NewArray creates a Binary array from the memory buffers used by the builder and resets the BinaryBuilder
// so it can be used to build a new array.
func (b *BinaryBuilder) NewArray() Interface {
return b.NewBinaryArray()
}
// NewBinaryArray creates a Binary array from the memory buffers used by the builder and resets the BinaryBuilder
// so it can be used to build a new array.
func (b *BinaryBuilder) NewBinaryArray() (a *Binary) {
data := b.newData()
a = NewBinaryData(data)
data.Release()
return
}
func (b *BinaryBuilder) newData() (data *Data) {
b.appendNextOffset()
offsets, values := b.offsets.Finish(), b.values.Finish()
data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, offsets, values}, nil, b.nulls, 0)
if offsets != nil {
offsets.Release()
}
if values != nil {
values.Release()
}
b.builder.reset()
return
}
func (b *BinaryBuilder) appendNextOffset() {
numBytes := b.values.Len()
// TODO(sgc): check binaryArrayMaximumCapacity?
b.offsets.AppendValue(int32(numBytes))
}
var (
_ Builder = (*BinaryBuilder)(nil)
)

View File

@@ -1,95 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"strings"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/memory"
)
// A type which represents an immutable sequence of boolean values.
type Boolean struct {
array
values []byte
}
// NewBoolean creates a boolean array from the data memory.Buffer and contains length elements.
// The nullBitmap buffer can be nil of there are no null values.
// If nulls is not known, use UnknownNullCount to calculate the value of NullN at runtime from the nullBitmap buffer.
func NewBoolean(length int, data *memory.Buffer, nullBitmap *memory.Buffer, nulls int) *Boolean {
return NewBooleanData(NewData(arrow.FixedWidthTypes.Boolean, length, []*memory.Buffer{nullBitmap, data}, nil, nulls, 0))
}
func NewBooleanData(data *Data) *Boolean {
a := &Boolean{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Boolean) Value(i int) bool {
if i < 0 || i >= a.array.data.length {
panic("arrow/array: index out of range")
}
return bitutil.BitIsSet(a.values, a.array.data.offset+i)
}
func (a *Boolean) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i := 0; i < a.Len(); i++ {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", a.Value(i))
}
}
o.WriteString("]")
return o.String()
}
func (a *Boolean) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = vals.Bytes()
}
}
func arrayEqualBoolean(left, right *Boolean) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
var (
_ Interface = (*Boolean)(nil)
)

View File

@@ -1,165 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
type BooleanBuilder struct {
builder
data *memory.Buffer
rawData []byte
}
func NewBooleanBuilder(mem memory.Allocator) *BooleanBuilder {
return &BooleanBuilder{builder: builder{refCount: 1, mem: mem}}
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (b *BooleanBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
}
}
func (b *BooleanBuilder) Append(v bool) {
b.Reserve(1)
b.UnsafeAppend(v)
}
func (b *BooleanBuilder) AppendByte(v byte) {
b.Reserve(1)
b.UnsafeAppend(v != 0)
}
func (b *BooleanBuilder) AppendNull() {
b.Reserve(1)
b.UnsafeAppendBoolToBitmap(false)
}
func (b *BooleanBuilder) UnsafeAppend(v bool) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
if v {
bitutil.SetBit(b.rawData, b.length)
} else {
bitutil.ClearBit(b.rawData, b.length)
}
b.length++
}
func (b *BooleanBuilder) AppendValues(v []bool, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
for i, vv := range v {
bitutil.SetBitTo(b.rawData, b.length+i, vv)
}
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
func (b *BooleanBuilder) init(capacity int) {
b.builder.init(capacity)
b.data = memory.NewResizableBuffer(b.mem)
bytesN := arrow.BooleanTraits.BytesRequired(capacity)
b.data.Resize(bytesN)
b.rawData = b.data.Bytes()
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *BooleanBuilder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *BooleanBuilder) Resize(n int) {
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(n, b.init)
b.data.Resize(arrow.BooleanTraits.BytesRequired(n))
b.rawData = b.data.Bytes()
}
}
// NewArray creates a Boolean array from the memory buffers used by the builder and resets the BooleanBuilder
// so it can be used to build a new array.
func (b *BooleanBuilder) NewArray() Interface {
return b.NewBooleanArray()
}
// NewBooleanArray creates a Boolean array from the memory buffers used by the builder and resets the BooleanBuilder
// so it can be used to build a new array.
func (b *BooleanBuilder) NewBooleanArray() (a *Boolean) {
data := b.newData()
a = NewBooleanData(data)
data.Release()
return
}
func (b *BooleanBuilder) newData() *Data {
bytesRequired := arrow.BooleanTraits.BytesRequired(b.length)
if bytesRequired > 0 && bytesRequired < b.data.Len() {
// trim buffers
b.data.Resize(bytesRequired)
}
res := NewData(arrow.FixedWidthTypes.Boolean, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
b.reset()
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
return res
}
var (
_ Builder = (*BooleanBuilder)(nil)
)

View File

@@ -1,127 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"sync/atomic"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// A bufferBuilder provides common functionality for populating memory with a sequence of type-specific values.
// Specialized implementations provide type-safe APIs for appending and accessing the memory.
type bufferBuilder struct {
refCount int64
mem memory.Allocator
buffer *memory.Buffer
length int
capacity int
bytes []byte
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (b *bufferBuilder) Retain() {
atomic.AddInt64(&b.refCount, 1)
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (b *bufferBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.buffer != nil {
b.buffer.Release()
b.buffer, b.bytes = nil, nil
}
}
}
// Len returns the length of the memory buffer in bytes.
func (b *bufferBuilder) Len() int { return b.length }
// Cap returns the total number of bytes that can be stored without allocating additional memory.
func (b *bufferBuilder) Cap() int { return b.capacity }
// Bytes returns a slice of length b.Len().
// The slice is only valid for use until the next buffer modification. That is, until the next call
// to Advance, Reset, Finish or any Append function. The slice aliases the buffer content at least until the next
// buffer modification.
func (b *bufferBuilder) Bytes() []byte { return b.bytes[:b.length] }
func (b *bufferBuilder) resize(elements int) {
if b.buffer == nil {
b.buffer = memory.NewResizableBuffer(b.mem)
}
b.buffer.Resize(elements)
oldCapacity := b.capacity
b.capacity = b.buffer.Cap()
b.bytes = b.buffer.Buf()
if b.capacity > oldCapacity {
memory.Set(b.bytes[oldCapacity:], 0)
}
}
// Advance increases the buffer by length and initializes the skipped bytes to zero.
func (b *bufferBuilder) Advance(length int) {
if b.capacity < b.length+length {
newCapacity := bitutil.NextPowerOf2(b.length + length)
b.resize(newCapacity)
}
b.length += length
}
// Append appends the contents of v to the buffer, resizing it if necessary.
func (b *bufferBuilder) Append(v []byte) {
if b.capacity < b.length+len(v) {
newCapacity := bitutil.NextPowerOf2(b.length + len(v))
b.resize(newCapacity)
}
b.unsafeAppend(v)
}
// Reset returns the buffer to an empty state. Reset releases the memory and sets the length and capacity to zero.
func (b *bufferBuilder) Reset() {
if b.buffer != nil {
b.buffer.Release()
}
b.buffer, b.bytes = nil, nil
b.capacity, b.length = 0, 0
}
// Finish TODO(sgc)
func (b *bufferBuilder) Finish() (buffer *memory.Buffer) {
if b.length > 0 {
b.buffer.ResizeNoShrink(b.length)
}
buffer = b.buffer
b.buffer = nil
b.Reset()
return
}
func (b *bufferBuilder) unsafeAppend(data []byte) {
copy(b.bytes[b.length:], data)
b.length += len(data)
}

View File

@@ -1,30 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import "github.com/apache/arrow/go/arrow/memory"
type byteBufferBuilder struct {
bufferBuilder
}
func newByteBufferBuilder(mem memory.Allocator) *byteBufferBuilder {
return &byteBufferBuilder{bufferBuilder: bufferBuilder{refCount: 1, mem: mem}}
}
func (b *byteBufferBuilder) Values() []byte { return b.Bytes() }
func (b *byteBufferBuilder) Value(i int) byte { return b.bytes[i] }

View File

@@ -1,58 +0,0 @@
// Code generated by array/bufferbuilder_numeric.gen.go.tmpl. DO NOT EDIT.
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/memory"
)
type int32BufferBuilder struct {
bufferBuilder
}
func newInt32BufferBuilder(mem memory.Allocator) *int32BufferBuilder {
return &int32BufferBuilder{bufferBuilder: bufferBuilder{refCount: 1, mem: mem}}
}
// AppendValues appends the contents of v to the buffer, growing the buffer as needed.
func (b *int32BufferBuilder) AppendValues(v []int32) { b.Append(arrow.Int32Traits.CastToBytes(v)) }
// Values returns a slice of length b.Len().
// The slice is only valid for use until the next buffer modification. That is, until the next call
// to Advance, Reset, Finish or any Append function. The slice aliases the buffer content at least until the next
// buffer modification.
func (b *int32BufferBuilder) Values() []int32 { return arrow.Int32Traits.CastFromBytes(b.Bytes()) }
// Value returns the int32 element at the index i. Value will panic if i is negative or ≥ Len.
func (b *int32BufferBuilder) Value(i int) int32 { return b.Values()[i] }
// Len returns the number of int32 elements in the buffer.
func (b *int32BufferBuilder) Len() int { return b.length / arrow.Int32SizeBytes }
// AppendValue appends v to the buffer, growing the buffer as needed.
func (b *int32BufferBuilder) AppendValue(v int32) {
if b.capacity < b.length+arrow.Int32SizeBytes {
newCapacity := bitutil.NextPowerOf2(b.length + arrow.Int32SizeBytes)
b.resize(newCapacity)
}
arrow.Int32Traits.PutValue(b.bytes[b.length:], v)
b.length += arrow.Int32SizeBytes
}

View File

@@ -1,61 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/memory"
)
{{range .In}}
{{$TypeNamePrefix := .name}}
{{if .Opt.BufferBuilder}}
type {{$TypeNamePrefix}}BufferBuilder struct {
bufferBuilder
}
func new{{.Name}}BufferBuilder(mem memory.Allocator) *{{$TypeNamePrefix}}BufferBuilder {
return &{{$TypeNamePrefix}}BufferBuilder{bufferBuilder:bufferBuilder{refCount: 1, mem:mem}}
}
// AppendValues appends the contents of v to the buffer, growing the buffer as needed.
func (b *{{$TypeNamePrefix}}BufferBuilder) AppendValues(v []{{.Type}}) { b.Append(arrow.{{.Name}}Traits.CastToBytes(v)) }
// Values returns a slice of length b.Len().
// The slice is only valid for use until the next buffer modification. That is, until the next call
// to Advance, Reset, Finish or any Append function. The slice aliases the buffer content at least until the next
// buffer modification.
func (b *{{$TypeNamePrefix}}BufferBuilder) Values() []{{.Type}} { return arrow.{{.Name}}Traits.CastFromBytes(b.Bytes()) }
// Value returns the {{.Type}} element at the index i. Value will panic if i is negative or ≥ Len.
func (b *{{$TypeNamePrefix}}BufferBuilder) Value(i int) {{.Type}} { return b.Values()[i] }
// Len returns the number of {{.Type}} elements in the buffer.
func (b *{{$TypeNamePrefix}}BufferBuilder) Len() int { return b.length/arrow.{{.Name}}SizeBytes }
// AppendValue appends v to the buffer, growing the buffer as needed.
func (b *{{$TypeNamePrefix}}BufferBuilder) AppendValue(v {{.Type}}) {
if b.capacity < b.length+arrow.{{.Name}}SizeBytes {
newCapacity := bitutil.NextPowerOf2(b.length + arrow.{{.Name}}SizeBytes)
b.resize(newCapacity)
}
arrow.{{.Name}}Traits.PutValue(b.bytes[b.length:], v)
b.length+=arrow.{{.Name}}SizeBytes
}
{{end}}
{{end}}

View File

@@ -1,273 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/memory"
)
const (
minBuilderCapacity = 1 << 5
)
// Builder provides an interface to build arrow arrays.
type Builder interface {
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
Retain()
// Release decreases the reference count by 1.
Release()
// Len returns the number of elements in the array builder.
Len() int
// Cap returns the total number of elements that can be stored
// without allocating additional memory.
Cap() int
// NullN returns the number of null values in the array builder.
NullN() int
// AppendNull adds a new null value to the array being built.
AppendNull()
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
Reserve(n int)
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
Resize(n int)
// NewArray creates a new array from the memory buffers used
// by the builder and resets the Builder so it can be used to build
// a new array.
NewArray() Interface
init(capacity int)
resize(newBits int, init func(int))
}
// builder provides common functionality for managing the validity bitmap (nulls) when building arrays.
type builder struct {
refCount int64
mem memory.Allocator
nullBitmap *memory.Buffer
nulls int
length int
capacity int
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (b *builder) Retain() {
atomic.AddInt64(&b.refCount, 1)
}
// Len returns the number of elements in the array builder.
func (b *builder) Len() int { return b.length }
// Cap returns the total number of elements that can be stored without allocating additional memory.
func (b *builder) Cap() int { return b.capacity }
// NullN returns the number of null values in the array builder.
func (b *builder) NullN() int { return b.nulls }
func (b *builder) init(capacity int) {
toAlloc := bitutil.CeilByte(capacity) / 8
b.nullBitmap = memory.NewResizableBuffer(b.mem)
b.nullBitmap.Resize(toAlloc)
b.capacity = capacity
memory.Set(b.nullBitmap.Buf(), 0)
}
func (b *builder) reset() {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
b.nulls = 0
b.length = 0
b.capacity = 0
}
func (b *builder) resize(newBits int, init func(int)) {
if b.nullBitmap == nil {
init(newBits)
return
}
newBytesN := bitutil.CeilByte(newBits) / 8
oldBytesN := b.nullBitmap.Len()
b.nullBitmap.Resize(newBytesN)
b.capacity = newBits
if oldBytesN < newBytesN {
// TODO(sgc): necessary?
memory.Set(b.nullBitmap.Buf()[oldBytesN:], 0)
}
if newBits < b.length {
b.length = newBits
b.nulls = newBits - bitutil.CountSetBits(b.nullBitmap.Buf(), 0, newBits)
}
}
func (b *builder) reserve(elements int, resize func(int)) {
if b.length+elements > b.capacity {
newCap := bitutil.NextPowerOf2(b.length + elements)
resize(newCap)
}
}
// unsafeAppendBoolsToBitmap appends the contents of valid to the validity bitmap.
// As an optimization, if the valid slice is empty, the next length bits will be set to valid (not null).
func (b *builder) unsafeAppendBoolsToBitmap(valid []bool, length int) {
if len(valid) == 0 {
b.unsafeSetValid(length)
return
}
byteOffset := b.length / 8
bitOffset := byte(b.length % 8)
nullBitmap := b.nullBitmap.Bytes()
bitSet := nullBitmap[byteOffset]
for _, v := range valid {
if bitOffset == 8 {
bitOffset = 0
nullBitmap[byteOffset] = bitSet
byteOffset++
bitSet = nullBitmap[byteOffset]
}
if v {
bitSet |= bitutil.BitMask[bitOffset]
} else {
bitSet &= bitutil.FlippedBitMask[bitOffset]
b.nulls++
}
bitOffset++
}
if bitOffset != 0 {
nullBitmap[byteOffset] = bitSet
}
b.length += len(valid)
}
// unsafeSetValid sets the next length bits to valid in the validity bitmap.
func (b *builder) unsafeSetValid(length int) {
padToByte := min(8-(b.length%8), length)
if padToByte == 8 {
padToByte = 0
}
bits := b.nullBitmap.Bytes()
for i := b.length; i < b.length+padToByte; i++ {
bitutil.SetBit(bits, i)
}
start := (b.length + padToByte) / 8
fastLength := (length - padToByte) / 8
memory.Set(bits[start:start+fastLength], 0xff)
newLength := b.length + length
// trailing bytes
for i := b.length + padToByte + (fastLength * 8); i < newLength; i++ {
bitutil.SetBit(bits, i)
}
b.length = newLength
}
func (b *builder) UnsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
func newBuilder(mem memory.Allocator, dtype arrow.DataType) Builder {
// FIXME(sbinet): use a type switch on dtype instead?
switch dtype.ID() {
case arrow.NULL:
case arrow.BOOL:
return NewBooleanBuilder(mem)
case arrow.UINT8:
return NewUint8Builder(mem)
case arrow.INT8:
return NewInt8Builder(mem)
case arrow.UINT16:
return NewUint16Builder(mem)
case arrow.INT16:
return NewInt16Builder(mem)
case arrow.UINT32:
return NewUint32Builder(mem)
case arrow.INT32:
return NewInt32Builder(mem)
case arrow.UINT64:
return NewUint64Builder(mem)
case arrow.INT64:
return NewInt64Builder(mem)
case arrow.FLOAT16:
return NewFloat16Builder(mem)
case arrow.FLOAT32:
return NewFloat32Builder(mem)
case arrow.FLOAT64:
return NewFloat64Builder(mem)
case arrow.STRING:
return NewStringBuilder(mem)
case arrow.BINARY:
return NewBinaryBuilder(mem, arrow.BinaryTypes.Binary)
case arrow.FIXED_SIZE_BINARY:
typ := dtype.(*arrow.FixedSizeBinaryType)
return NewFixedSizeBinaryBuilder(mem, typ)
case arrow.DATE32:
case arrow.DATE64:
case arrow.TIMESTAMP:
case arrow.TIME32:
typ := dtype.(*arrow.Time32Type)
return NewTime32Builder(mem, typ)
case arrow.TIME64:
typ := dtype.(*arrow.Time64Type)
return NewTime64Builder(mem, typ)
case arrow.INTERVAL:
case arrow.DECIMAL:
case arrow.LIST:
typ := dtype.(*arrow.ListType)
return NewListBuilder(mem, typ.Elem())
case arrow.STRUCT:
typ := dtype.(*arrow.StructType)
return NewStructBuilder(mem, typ)
case arrow.UNION:
case arrow.DICTIONARY:
case arrow.MAP:
case arrow.EXTENSION:
case arrow.FIXED_SIZE_LIST:
typ := dtype.(*arrow.FixedSizeListType)
return NewFixedSizeListBuilder(mem, typ.Len(), typ.Elem())
case arrow.DURATION:
}
panic(fmt.Errorf("arrow/array: unsupported builder for %T", dtype))
}

View File

@@ -1,474 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"math"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/float16"
"github.com/pkg/errors"
)
// RecordEqual reports whether the two provided records are equal.
func RecordEqual(left, right Record) bool {
switch {
case left.NumCols() != right.NumCols():
return false
case left.NumRows() != right.NumRows():
return false
}
for i := range left.Columns() {
lc := left.Column(i)
rc := right.Column(i)
if !ArrayEqual(lc, rc) {
return false
}
}
return true
}
// RecordApproxEqual reports whether the two provided records are approximately equal.
// For non-floating point columns, it is equivalent to RecordEqual.
func RecordApproxEqual(left, right Record, opts ...EqualOption) bool {
switch {
case left.NumCols() != right.NumCols():
return false
case left.NumRows() != right.NumRows():
return false
}
opt := newEqualOption(opts...)
for i := range left.Columns() {
lc := left.Column(i)
rc := right.Column(i)
if !arrayApproxEqual(lc, rc, opt) {
return false
}
}
return true
}
// ArrayEqual reports whether the two provided arrays are equal.
func ArrayEqual(left, right Interface) bool {
switch {
case !baseArrayEqual(left, right):
return false
case left.Len() == 0:
return true
case left.NullN() == left.Len():
return true
}
// at this point, we know both arrays have same type, same length, same number of nulls
// and nulls at the same place.
// compare the values.
switch l := left.(type) {
case *Null:
return true
case *Boolean:
r := right.(*Boolean)
return arrayEqualBoolean(l, r)
case *FixedSizeBinary:
r := right.(*FixedSizeBinary)
return arrayEqualFixedSizeBinary(l, r)
case *Binary:
r := right.(*Binary)
return arrayEqualBinary(l, r)
case *String:
r := right.(*String)
return arrayEqualString(l, r)
case *Int8:
r := right.(*Int8)
return arrayEqualInt8(l, r)
case *Int16:
r := right.(*Int16)
return arrayEqualInt16(l, r)
case *Int32:
r := right.(*Int32)
return arrayEqualInt32(l, r)
case *Int64:
r := right.(*Int64)
return arrayEqualInt64(l, r)
case *Uint8:
r := right.(*Uint8)
return arrayEqualUint8(l, r)
case *Uint16:
r := right.(*Uint16)
return arrayEqualUint16(l, r)
case *Uint32:
r := right.(*Uint32)
return arrayEqualUint32(l, r)
case *Uint64:
r := right.(*Uint64)
return arrayEqualUint64(l, r)
case *Float16:
r := right.(*Float16)
return arrayEqualFloat16(l, r)
case *Float32:
r := right.(*Float32)
return arrayEqualFloat32(l, r)
case *Float64:
r := right.(*Float64)
return arrayEqualFloat64(l, r)
case *Decimal128:
r := right.(*Decimal128)
return arrayEqualDecimal128(l, r)
case *Date32:
r := right.(*Date32)
return arrayEqualDate32(l, r)
case *Date64:
r := right.(*Date64)
return arrayEqualDate64(l, r)
case *Time32:
r := right.(*Time32)
return arrayEqualTime32(l, r)
case *Time64:
r := right.(*Time64)
return arrayEqualTime64(l, r)
case *Timestamp:
r := right.(*Timestamp)
return arrayEqualTimestamp(l, r)
case *List:
r := right.(*List)
return arrayEqualList(l, r)
case *FixedSizeList:
r := right.(*FixedSizeList)
return arrayEqualFixedSizeList(l, r)
case *Struct:
r := right.(*Struct)
return arrayEqualStruct(l, r)
case *MonthInterval:
r := right.(*MonthInterval)
return arrayEqualMonthInterval(l, r)
case *DayTimeInterval:
r := right.(*DayTimeInterval)
return arrayEqualDayTimeInterval(l, r)
case *Duration:
r := right.(*Duration)
return arrayEqualDuration(l, r)
default:
panic(errors.Errorf("arrow/array: unknown array type %T", l))
}
}
// ArraySliceEqual reports whether slices left[lbeg:lend] and right[rbeg:rend] are equal.
func ArraySliceEqual(left Interface, lbeg, lend int64, right Interface, rbeg, rend int64) bool {
l := NewSlice(left, lbeg, lend)
defer l.Release()
r := NewSlice(right, rbeg, rend)
defer r.Release()
return ArrayEqual(l, r)
}
const defaultAbsoluteTolerance = 1e-5
type equalOption struct {
atol float64 // absolute tolerance
nansEq bool // whether NaNs are considered equal.
}
func (eq equalOption) f16(f1, f2 float16.Num) bool {
v1 := float64(f1.Float32())
v2 := float64(f2.Float32())
switch {
case eq.nansEq:
return math.Abs(v1-v2) <= eq.atol || (math.IsNaN(v1) && math.IsNaN(v2))
default:
return math.Abs(v1-v2) <= eq.atol
}
}
func (eq equalOption) f32(f1, f2 float32) bool {
v1 := float64(f1)
v2 := float64(f2)
switch {
case eq.nansEq:
return math.Abs(v1-v2) <= eq.atol || (math.IsNaN(v1) && math.IsNaN(v2))
default:
return math.Abs(v1-v2) <= eq.atol
}
}
func (eq equalOption) f64(v1, v2 float64) bool {
switch {
case eq.nansEq:
return math.Abs(v1-v2) <= eq.atol || (math.IsNaN(v1) && math.IsNaN(v2))
default:
return math.Abs(v1-v2) <= eq.atol
}
}
func newEqualOption(opts ...EqualOption) equalOption {
eq := equalOption{
atol: defaultAbsoluteTolerance,
nansEq: false,
}
for _, opt := range opts {
opt(&eq)
}
return eq
}
// EqualOption is a functional option type used to configure how Records and Arrays are compared.
type EqualOption func(*equalOption)
// WithNaNsEqual configures the comparison functions so that NaNs are considered equal.
func WithNaNsEqual(v bool) EqualOption {
return func(o *equalOption) {
o.nansEq = v
}
}
// WithAbsTolerance configures the comparison functions so that 2 floating point values
// v1 and v2 are considered equal if |v1-v2| <= atol.
func WithAbsTolerance(atol float64) EqualOption {
return func(o *equalOption) {
o.atol = atol
}
}
// ArrayApproxEqual reports whether the two provided arrays are approximately equal.
// For non-floating point arrays, it is equivalent to ArrayEqual.
func ArrayApproxEqual(left, right Interface, opts ...EqualOption) bool {
opt := newEqualOption(opts...)
return arrayApproxEqual(left, right, opt)
}
func arrayApproxEqual(left, right Interface, opt equalOption) bool {
switch {
case !baseArrayEqual(left, right):
return false
case left.Len() == 0:
return true
case left.NullN() == left.Len():
return true
}
// at this point, we know both arrays have same type, same length, same number of nulls
// and nulls at the same place.
// compare the values.
switch l := left.(type) {
case *Null:
return true
case *Boolean:
r := right.(*Boolean)
return arrayEqualBoolean(l, r)
case *FixedSizeBinary:
r := right.(*FixedSizeBinary)
return arrayEqualFixedSizeBinary(l, r)
case *Binary:
r := right.(*Binary)
return arrayEqualBinary(l, r)
case *String:
r := right.(*String)
return arrayEqualString(l, r)
case *Int8:
r := right.(*Int8)
return arrayEqualInt8(l, r)
case *Int16:
r := right.(*Int16)
return arrayEqualInt16(l, r)
case *Int32:
r := right.(*Int32)
return arrayEqualInt32(l, r)
case *Int64:
r := right.(*Int64)
return arrayEqualInt64(l, r)
case *Uint8:
r := right.(*Uint8)
return arrayEqualUint8(l, r)
case *Uint16:
r := right.(*Uint16)
return arrayEqualUint16(l, r)
case *Uint32:
r := right.(*Uint32)
return arrayEqualUint32(l, r)
case *Uint64:
r := right.(*Uint64)
return arrayEqualUint64(l, r)
case *Float16:
r := right.(*Float16)
return arrayApproxEqualFloat16(l, r, opt)
case *Float32:
r := right.(*Float32)
return arrayApproxEqualFloat32(l, r, opt)
case *Float64:
r := right.(*Float64)
return arrayApproxEqualFloat64(l, r, opt)
case *Decimal128:
r := right.(*Decimal128)
return arrayEqualDecimal128(l, r)
case *Date32:
r := right.(*Date32)
return arrayEqualDate32(l, r)
case *Date64:
r := right.(*Date64)
return arrayEqualDate64(l, r)
case *Time32:
r := right.(*Time32)
return arrayEqualTime32(l, r)
case *Time64:
r := right.(*Time64)
return arrayEqualTime64(l, r)
case *Timestamp:
r := right.(*Timestamp)
return arrayEqualTimestamp(l, r)
case *List:
r := right.(*List)
return arrayApproxEqualList(l, r, opt)
case *FixedSizeList:
r := right.(*FixedSizeList)
return arrayApproxEqualFixedSizeList(l, r, opt)
case *Struct:
r := right.(*Struct)
return arrayApproxEqualStruct(l, r, opt)
case *MonthInterval:
r := right.(*MonthInterval)
return arrayEqualMonthInterval(l, r)
case *DayTimeInterval:
r := right.(*DayTimeInterval)
return arrayEqualDayTimeInterval(l, r)
case *Duration:
r := right.(*Duration)
return arrayEqualDuration(l, r)
default:
panic(errors.Errorf("arrow/array: unknown array type %T", l))
}
return false
}
func baseArrayEqual(left, right Interface) bool {
switch {
case left.Len() != right.Len():
return false
case left.NullN() != right.NullN():
return false
case !arrow.TypeEquals(left.DataType(), right.DataType()): // We do not check for metadata as in the C++ implementation.
return false
case !validityBitmapEqual(left, right):
return false
}
return true
}
func validityBitmapEqual(left, right Interface) bool {
// TODO(alexandreyc): make it faster by comparing byte slices of the validity bitmap?
n := left.Len()
if n != right.Len() {
return false
}
for i := 0; i < n; i++ {
if left.IsNull(i) != right.IsNull(i) {
return false
}
}
return true
}
func arrayApproxEqualFloat16(left, right *Float16, opt equalOption) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if !opt.f16(left.Value(i), right.Value(i)) {
return false
}
}
return true
}
func arrayApproxEqualFloat32(left, right *Float32, opt equalOption) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if !opt.f32(left.Value(i), right.Value(i)) {
return false
}
}
return true
}
func arrayApproxEqualFloat64(left, right *Float64, opt equalOption) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if !opt.f64(left.Value(i), right.Value(i)) {
return false
}
}
return true
}
func arrayApproxEqualList(left, right *List, opt equalOption) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
o := func() bool {
l := left.newListValue(i)
defer l.Release()
r := right.newListValue(i)
defer r.Release()
return arrayApproxEqual(l, r, opt)
}()
if !o {
return false
}
}
return true
}
func arrayApproxEqualFixedSizeList(left, right *FixedSizeList, opt equalOption) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
o := func() bool {
l := left.newListValue(i)
defer l.Release()
r := right.newListValue(i)
defer r.Release()
return arrayApproxEqual(l, r, opt)
}()
if !o {
return false
}
}
return true
}
func arrayApproxEqualStruct(left, right *Struct, opt equalOption) bool {
for i, lf := range left.fields {
rf := right.fields[i]
if !arrayApproxEqual(lf, rf, opt) {
return false
}
}
return true
}

View File

@@ -1,133 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// A type which represents the memory and metadata for an Arrow array.
type Data struct {
refCount int64
dtype arrow.DataType
nulls int
offset int
length int
buffers []*memory.Buffer // TODO(sgc): should this be an interface?
childData []*Data // TODO(sgc): managed by ListArray, StructArray and UnionArray types
}
func NewData(dtype arrow.DataType, length int, buffers []*memory.Buffer, childData []*Data, nulls, offset int) *Data {
for _, b := range buffers {
if b != nil {
b.Retain()
}
}
for _, child := range childData {
if child != nil {
child.Retain()
}
}
return &Data{
refCount: 1,
dtype: dtype,
nulls: nulls,
length: length,
offset: offset,
buffers: buffers,
childData: childData,
}
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (d *Data) Retain() {
atomic.AddInt64(&d.refCount, 1)
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (d *Data) Release() {
debug.Assert(atomic.LoadInt64(&d.refCount) > 0, "too many releases")
if atomic.AddInt64(&d.refCount, -1) == 0 {
for _, b := range d.buffers {
if b != nil {
b.Release()
}
}
for _, b := range d.childData {
b.Release()
}
d.buffers, d.childData = nil, nil
}
}
func (d *Data) DataType() arrow.DataType { return d.dtype }
func (d *Data) NullN() int { return d.nulls }
func (d *Data) Len() int { return d.length }
func (d *Data) Offset() int { return d.offset }
func (d *Data) Buffers() []*memory.Buffer { return d.buffers }
// NewSliceData returns a new slice that shares backing data with the input.
// The returned Data slice starts at i and extends j-i elements, such as:
// slice := data[i:j]
// The returned value must be Release'd after use.
//
// NewSliceData panics if the slice is outside the valid range of the input Data.
// NewSliceData panics if j < i.
func NewSliceData(data *Data, i, j int64) *Data {
if j > int64(data.length) || i > j || data.offset+int(i) > data.offset+data.length {
panic("arrow/array: index out of range")
}
for _, b := range data.buffers {
if b != nil {
b.Retain()
}
}
for _, child := range data.childData {
if child != nil {
child.Retain()
}
}
o := &Data{
refCount: 1,
dtype: data.dtype,
nulls: UnknownNullCount,
length: int(j - i),
offset: data.offset + int(i),
buffers: data.buffers,
childData: data.childData,
}
if data.nulls == 0 {
o.nulls = 0
}
return o
}

View File

@@ -1,235 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array // import "github.com/apache/arrow/go/arrow/array"
import (
"fmt"
"strings"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/decimal128"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// A type which represents an immutable sequence of 128-bit decimal values.
type Decimal128 struct {
array
values []decimal128.Num
}
func NewDecimal128Data(data *Data) *Decimal128 {
a := &Decimal128{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Decimal128) Value(i int) decimal128.Num { return a.values[i] }
func (a *Decimal128) Values() []decimal128.Num { return a.values }
func (a *Decimal128) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i := 0; i < a.Len(); i++ {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", a.Value(i))
}
}
o.WriteString("]")
return o.String()
}
func (a *Decimal128) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Decimal128Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualDecimal128(left, right *Decimal128) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
type Decimal128Builder struct {
builder
dtype *arrow.Decimal128Type
data *memory.Buffer
rawData []decimal128.Num
}
func NewDecimal128Builder(mem memory.Allocator, dtype *arrow.Decimal128Type) *Decimal128Builder {
return &Decimal128Builder{
builder: builder{refCount: 1, mem: mem},
dtype: dtype,
}
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *Decimal128Builder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
}
}
func (b *Decimal128Builder) Append(v decimal128.Num) {
b.Reserve(1)
b.UnsafeAppend(v)
}
func (b *Decimal128Builder) UnsafeAppend(v decimal128.Num) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
b.rawData[b.length] = v
b.length++
}
func (b *Decimal128Builder) AppendNull() {
b.Reserve(1)
b.UnsafeAppendBoolToBitmap(false)
}
func (b *Decimal128Builder) UnsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
// AppendValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *Decimal128Builder) AppendValues(v []decimal128.Num, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
if len(v) > 0 {
arrow.Decimal128Traits.Copy(b.rawData[b.length:], v)
}
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
func (b *Decimal128Builder) init(capacity int) {
b.builder.init(capacity)
b.data = memory.NewResizableBuffer(b.mem)
bytesN := arrow.Decimal128Traits.BytesRequired(capacity)
b.data.Resize(bytesN)
b.rawData = arrow.Decimal128Traits.CastFromBytes(b.data.Bytes())
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *Decimal128Builder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *Decimal128Builder) Resize(n int) {
nBuilder := n
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(nBuilder, b.init)
b.data.Resize(arrow.Decimal128Traits.BytesRequired(n))
b.rawData = arrow.Decimal128Traits.CastFromBytes(b.data.Bytes())
}
}
// NewArray creates a Decimal128 array from the memory buffers used by the builder and resets the Decimal128Builder
// so it can be used to build a new array.
func (b *Decimal128Builder) NewArray() Interface {
return b.NewDecimal128Array()
}
// NewDecimal128Array creates a Decimal128 array from the memory buffers used by the builder and resets the Decimal128Builder
// so it can be used to build a new array.
func (b *Decimal128Builder) NewDecimal128Array() (a *Decimal128) {
data := b.newData()
a = NewDecimal128Data(data)
data.Release()
return
}
func (b *Decimal128Builder) newData() (data *Data) {
bytesRequired := arrow.Decimal128Traits.BytesRequired(b.length)
if bytesRequired > 0 && bytesRequired < b.data.Len() {
// trim buffers
b.data.Resize(bytesRequired)
}
data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
b.reset()
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
return
}
var (
_ Interface = (*Decimal128)(nil)
_ Builder = (*Decimal128Builder)(nil)
)

View File

@@ -1,20 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Package array provides implementations of various Arrow array types.
*/
package array

View File

@@ -1,240 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"strings"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// FixedSizeList represents an immutable sequence of N array values.
type FixedSizeList struct {
array
n int32
values Interface
}
// NewFixedSizeListData returns a new List array value, from data.
func NewFixedSizeListData(data *Data) *FixedSizeList {
a := &FixedSizeList{}
a.refCount = 1
a.setData(data)
return a
}
func (a *FixedSizeList) ListValues() Interface { return a.values }
func (a *FixedSizeList) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i := 0; i < a.Len(); i++ {
if i > 0 {
o.WriteString(" ")
}
if !a.IsValid(i) {
o.WriteString("(null)")
continue
}
sub := a.newListValue(i)
fmt.Fprintf(o, "%v", sub)
sub.Release()
}
o.WriteString("]")
return o.String()
}
func (a *FixedSizeList) newListValue(i int) Interface {
n := int64(a.n)
off := int64(a.array.data.offset)
beg := (off + int64(i)) * n
end := (off + int64(i+1)) * n
sli := NewSlice(a.values, beg, end)
return sli
}
func (a *FixedSizeList) setData(data *Data) {
a.array.setData(data)
a.n = a.DataType().(*arrow.FixedSizeListType).Len()
a.values = MakeFromData(data.childData[0])
}
func arrayEqualFixedSizeList(left, right *FixedSizeList) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
o := func() bool {
l := left.newListValue(i)
defer l.Release()
r := right.newListValue(i)
defer r.Release()
return ArrayEqual(l, r)
}()
if !o {
return false
}
}
return true
}
// Len returns the number of elements in the array.
func (a *FixedSizeList) Len() int { return a.array.Len() }
func (a *FixedSizeList) Retain() {
a.array.Retain()
a.values.Retain()
}
func (a *FixedSizeList) Release() {
a.array.Release()
a.values.Release()
}
type FixedSizeListBuilder struct {
builder
etype arrow.DataType // data type of the list's elements.
n int32 // number of elements in the fixed-size list.
values Builder // value builder for the list's elements.
}
// NewFixedSizeListBuilder returns a builder, using the provided memory allocator.
// The created list builder will create a list whose elements will be of type etype.
func NewFixedSizeListBuilder(mem memory.Allocator, n int32, etype arrow.DataType) *FixedSizeListBuilder {
return &FixedSizeListBuilder{
builder: builder{refCount: 1, mem: mem},
etype: etype,
n: n,
values: newBuilder(mem, etype),
}
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *FixedSizeListBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.values != nil {
b.values.Release()
b.values = nil
}
}
}
func (b *FixedSizeListBuilder) Append(v bool) {
b.Reserve(1)
b.unsafeAppendBoolToBitmap(v)
}
func (b *FixedSizeListBuilder) AppendNull() {
b.Reserve(1)
b.unsafeAppendBoolToBitmap(false)
}
func (b *FixedSizeListBuilder) AppendValues(valid []bool) {
b.Reserve(len(valid))
b.builder.unsafeAppendBoolsToBitmap(valid, len(valid))
}
func (b *FixedSizeListBuilder) unsafeAppend(v bool) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
b.length++
}
func (b *FixedSizeListBuilder) unsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
func (b *FixedSizeListBuilder) init(capacity int) {
b.builder.init(capacity)
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *FixedSizeListBuilder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *FixedSizeListBuilder) Resize(n int) {
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(n, b.builder.init)
}
}
func (b *FixedSizeListBuilder) ValueBuilder() Builder {
return b.values
}
// NewArray creates a List array from the memory buffers used by the builder and resets the FixedSizeListBuilder
// so it can be used to build a new array.
func (b *FixedSizeListBuilder) NewArray() Interface {
return b.NewListArray()
}
// NewListArray creates a List array from the memory buffers used by the builder and resets the FixedSizeListBuilder
// so it can be used to build a new array.
func (b *FixedSizeListBuilder) NewListArray() (a *FixedSizeList) {
data := b.newData()
a = NewFixedSizeListData(data)
data.Release()
return
}
func (b *FixedSizeListBuilder) newData() (data *Data) {
values := b.values.NewArray()
defer values.Release()
data = NewData(
arrow.FixedSizeListOf(b.n, b.etype), b.length,
[]*memory.Buffer{b.nullBitmap},
[]*Data{values.Data()},
b.nulls,
0,
)
b.reset()
return
}
var (
_ Interface = (*FixedSizeList)(nil)
_ Builder = (*FixedSizeListBuilder)(nil)
)

View File

@@ -1,95 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"bytes"
"fmt"
"strings"
"github.com/apache/arrow/go/arrow"
)
// A type which represents an immutable sequence of fixed-length binary strings.
type FixedSizeBinary struct {
array
valueBytes []byte
bytewidth int32
}
// NewFixedSizeBinaryData constructs a new fixed-size binary array from data.
func NewFixedSizeBinaryData(data *Data) *FixedSizeBinary {
a := &FixedSizeBinary{bytewidth: int32(data.DataType().(arrow.FixedWidthDataType).BitWidth() / 8)}
a.refCount = 1
a.setData(data)
return a
}
// Value returns the fixed-size slice at index i. This value should not be mutated.
func (a *FixedSizeBinary) Value(i int) []byte {
i += a.array.data.offset
var (
bw = int(a.bytewidth)
beg = i * bw
end = (i + 1) * bw
)
return a.valueBytes[beg:end]
}
func (a *FixedSizeBinary) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i := 0; i < a.Len(); i++ {
if i > 0 {
o.WriteString(" ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%q", a.Value(i))
}
}
o.WriteString("]")
return o.String()
}
func (a *FixedSizeBinary) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.valueBytes = vals.Bytes()
}
}
func arrayEqualFixedSizeBinary(left, right *FixedSizeBinary) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if bytes.Compare(left.Value(i), right.Value(i)) != 0 {
return false
}
}
return true
}
var (
_ Interface = (*FixedSizeBinary)(nil)
)

View File

@@ -1,154 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// A FixedSizeBinaryBuilder is used to build a FixedSizeBinary array using the Append methods.
type FixedSizeBinaryBuilder struct {
builder
dtype *arrow.FixedSizeBinaryType
values *byteBufferBuilder
}
func NewFixedSizeBinaryBuilder(mem memory.Allocator, dtype *arrow.FixedSizeBinaryType) *FixedSizeBinaryBuilder {
b := &FixedSizeBinaryBuilder{
builder: builder{refCount: 1, mem: mem},
dtype: dtype,
values: newByteBufferBuilder(mem),
}
return b
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (b *FixedSizeBinaryBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.values != nil {
b.values.Release()
b.values = nil
}
}
}
func (b *FixedSizeBinaryBuilder) Append(v []byte) {
if len(v) != b.dtype.ByteWidth {
// TODO(alexandre): should we return an error instead?
panic("len(v) != b.dtype.ByteWidth")
}
b.Reserve(1)
b.values.Append(v)
b.UnsafeAppendBoolToBitmap(true)
}
func (b *FixedSizeBinaryBuilder) AppendNull() {
b.Reserve(1)
b.values.Advance(b.dtype.ByteWidth)
b.UnsafeAppendBoolToBitmap(false)
}
// AppendValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *FixedSizeBinaryBuilder) AppendValues(v [][]byte, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
for _, vv := range v {
switch len(vv) {
case 0:
b.values.Advance(b.dtype.ByteWidth)
case b.dtype.ByteWidth:
b.values.Append(vv)
default:
panic(fmt.Errorf("array: invalid binary length (got=%d, want=%d)", len(vv), b.dtype.ByteWidth))
}
}
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
func (b *FixedSizeBinaryBuilder) init(capacity int) {
b.builder.init(capacity)
b.values.resize(capacity * b.dtype.ByteWidth)
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *FixedSizeBinaryBuilder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *FixedSizeBinaryBuilder) Resize(n int) {
b.builder.resize(n, b.init)
}
// NewArray creates a FixedSizeBinary array from the memory buffers used by the
// builder and resets the FixedSizeBinaryBuilder so it can be used to build a new array.
func (b *FixedSizeBinaryBuilder) NewArray() Interface {
return b.NewFixedSizeBinaryArray()
}
// NewFixedSizeBinaryArray creates a FixedSizeBinary array from the memory buffers used by the builder and resets the FixedSizeBinaryBuilder
// so it can be used to build a new array.
func (b *FixedSizeBinaryBuilder) NewFixedSizeBinaryArray() (a *FixedSizeBinary) {
data := b.newData()
a = NewFixedSizeBinaryData(data)
data.Release()
return
}
func (b *FixedSizeBinaryBuilder) newData() (data *Data) {
values := b.values.Finish()
data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, values}, nil, b.nulls, 0)
if values != nil {
values.Release()
}
b.builder.reset()
return
}
var (
_ Builder = (*FixedSizeBinaryBuilder)(nil)
)

View File

@@ -1,87 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"strings"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/float16"
)
// A type which represents an immutable sequence of Float16 values.
type Float16 struct {
array
values []float16.Num
}
func NewFloat16Data(data *Data) *Float16 {
a := &Float16{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Float16) Value(i int) float16.Num { return a.values[i] }
func (a *Float16) Values() []float16.Num { return a.values }
func (a *Float16) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i := 0; i < a.Len(); i++ {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", a.values[i].Float32())
}
}
o.WriteString("]")
return o.String()
}
func (a *Float16) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Float16Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualFloat16(left, right *Float16) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
var (
_ Interface = (*Float16)(nil)
)

View File

@@ -1,165 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/float16"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
type Float16Builder struct {
builder
data *memory.Buffer
rawData []float16.Num
}
func NewFloat16Builder(mem memory.Allocator) *Float16Builder {
return &Float16Builder{builder: builder{refCount: 1, mem: mem}}
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *Float16Builder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
}
}
func (b *Float16Builder) Append(v float16.Num) {
b.Reserve(1)
b.UnsafeAppend(v)
}
func (b *Float16Builder) UnsafeAppend(v float16.Num) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
b.rawData[b.length] = v
b.length++
}
func (b *Float16Builder) AppendNull() {
b.Reserve(1)
b.UnsafeAppendBoolToBitmap(false)
}
func (b *Float16Builder) UnsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
// AppendValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *Float16Builder) AppendValues(v []float16.Num, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
if len(v) > 0 {
arrow.Float16Traits.Copy(b.rawData[b.length:], v)
}
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
func (b *Float16Builder) init(capacity int) {
b.builder.init(capacity)
b.data = memory.NewResizableBuffer(b.mem)
bytesN := arrow.Uint16Traits.BytesRequired(capacity)
b.data.Resize(bytesN)
b.rawData = arrow.Float16Traits.CastFromBytes(b.data.Bytes())
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *Float16Builder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *Float16Builder) Resize(n int) {
nBuilder := n
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(nBuilder, b.init)
b.data.Resize(arrow.Float16Traits.BytesRequired(n))
b.rawData = arrow.Float16Traits.CastFromBytes(b.data.Bytes())
}
}
// NewArray creates a Float16 array from the memory buffers used by the builder and resets the Float16Builder
// so it can be used to build a new array.
func (b *Float16Builder) NewArray() Interface {
return b.NewFloat16Array()
}
// NewFloat16Array creates a Float16 array from the memory buffers used by the builder and resets the Float16Builder
// so it can be used to build a new array.
func (b *Float16Builder) NewFloat16Array() (a *Float16) {
data := b.newData()
a = NewFloat16Data(data)
data.Release()
return
}
func (b *Float16Builder) newData() (data *Data) {
bytesRequired := arrow.Float16Traits.BytesRequired(b.length)
if bytesRequired > 0 && bytesRequired < b.data.Len() {
// trim buffers
b.data.Resize(bytesRequired)
}
data = NewData(arrow.FixedWidthTypes.Float16, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
b.reset()
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
return
}

View File

@@ -1,434 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array // import "github.com/apache/arrow/go/arrow/array"
import (
"fmt"
"strings"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
"github.com/pkg/errors"
)
func NewIntervalData(data *Data) Interface {
switch data.dtype.(type) {
case *arrow.MonthIntervalType:
return NewMonthIntervalData(data)
case *arrow.DayTimeIntervalType:
return NewDayTimeIntervalData(data)
default:
panic(errors.Errorf("arrow/array: unknown interval data type %T", data.dtype))
}
}
// A type which represents an immutable sequence of arrow.MonthInterval values.
type MonthInterval struct {
array
values []arrow.MonthInterval
}
func NewMonthIntervalData(data *Data) *MonthInterval {
a := &MonthInterval{}
a.refCount = 1
a.setData(data)
return a
}
func (a *MonthInterval) Value(i int) arrow.MonthInterval { return a.values[i] }
func (a *MonthInterval) MonthIntervalValues() []arrow.MonthInterval { return a.values }
func (a *MonthInterval) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *MonthInterval) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.MonthIntervalTraits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualMonthInterval(left, right *MonthInterval) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
type MonthIntervalBuilder struct {
builder
data *memory.Buffer
rawData []arrow.MonthInterval
}
func NewMonthIntervalBuilder(mem memory.Allocator) *MonthIntervalBuilder {
return &MonthIntervalBuilder{builder: builder{refCount: 1, mem: mem}}
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *MonthIntervalBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
}
}
func (b *MonthIntervalBuilder) Append(v arrow.MonthInterval) {
b.Reserve(1)
b.UnsafeAppend(v)
}
func (b *MonthIntervalBuilder) AppendNull() {
b.Reserve(1)
b.UnsafeAppendBoolToBitmap(false)
}
func (b *MonthIntervalBuilder) UnsafeAppend(v arrow.MonthInterval) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
b.rawData[b.length] = v
b.length++
}
func (b *MonthIntervalBuilder) UnsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
// AppendValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *MonthIntervalBuilder) AppendValues(v []arrow.MonthInterval, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
arrow.MonthIntervalTraits.Copy(b.rawData[b.length:], v)
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
func (b *MonthIntervalBuilder) init(capacity int) {
b.builder.init(capacity)
b.data = memory.NewResizableBuffer(b.mem)
bytesN := arrow.MonthIntervalTraits.BytesRequired(capacity)
b.data.Resize(bytesN)
b.rawData = arrow.MonthIntervalTraits.CastFromBytes(b.data.Bytes())
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *MonthIntervalBuilder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *MonthIntervalBuilder) Resize(n int) {
nBuilder := n
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(nBuilder, b.init)
b.data.Resize(arrow.MonthIntervalTraits.BytesRequired(n))
b.rawData = arrow.MonthIntervalTraits.CastFromBytes(b.data.Bytes())
}
}
// NewArray creates a MonthInterval array from the memory buffers used by the builder and resets the MonthIntervalBuilder
// so it can be used to build a new array.
func (b *MonthIntervalBuilder) NewArray() Interface {
return b.NewMonthIntervalArray()
}
// NewMonthIntervalArray creates a MonthInterval array from the memory buffers used by the builder and resets the MonthIntervalBuilder
// so it can be used to build a new array.
func (b *MonthIntervalBuilder) NewMonthIntervalArray() (a *MonthInterval) {
data := b.newData()
a = NewMonthIntervalData(data)
data.Release()
return
}
func (b *MonthIntervalBuilder) newData() (data *Data) {
bytesRequired := arrow.MonthIntervalTraits.BytesRequired(b.length)
if bytesRequired > 0 && bytesRequired < b.data.Len() {
// trim buffers
b.data.Resize(bytesRequired)
}
data = NewData(arrow.FixedWidthTypes.MonthInterval, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
b.reset()
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
return
}
// A type which represents an immutable sequence of arrow.DayTimeInterval values.
type DayTimeInterval struct {
array
values []arrow.DayTimeInterval
}
func NewDayTimeIntervalData(data *Data) *DayTimeInterval {
a := &DayTimeInterval{}
a.refCount = 1
a.setData(data)
return a
}
func (a *DayTimeInterval) Value(i int) arrow.DayTimeInterval { return a.values[i] }
func (a *DayTimeInterval) DayTimeIntervalValues() []arrow.DayTimeInterval { return a.values }
func (a *DayTimeInterval) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *DayTimeInterval) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.DayTimeIntervalTraits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualDayTimeInterval(left, right *DayTimeInterval) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
type DayTimeIntervalBuilder struct {
builder
data *memory.Buffer
rawData []arrow.DayTimeInterval
}
func NewDayTimeIntervalBuilder(mem memory.Allocator) *DayTimeIntervalBuilder {
return &DayTimeIntervalBuilder{builder: builder{refCount: 1, mem: mem}}
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *DayTimeIntervalBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
}
}
func (b *DayTimeIntervalBuilder) Append(v arrow.DayTimeInterval) {
b.Reserve(1)
b.UnsafeAppend(v)
}
func (b *DayTimeIntervalBuilder) AppendNull() {
b.Reserve(1)
b.UnsafeAppendBoolToBitmap(false)
}
func (b *DayTimeIntervalBuilder) UnsafeAppend(v arrow.DayTimeInterval) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
b.rawData[b.length] = v
b.length++
}
func (b *DayTimeIntervalBuilder) UnsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
// AppendValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *DayTimeIntervalBuilder) AppendValues(v []arrow.DayTimeInterval, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
arrow.DayTimeIntervalTraits.Copy(b.rawData[b.length:], v)
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
func (b *DayTimeIntervalBuilder) init(capacity int) {
b.builder.init(capacity)
b.data = memory.NewResizableBuffer(b.mem)
bytesN := arrow.DayTimeIntervalTraits.BytesRequired(capacity)
b.data.Resize(bytesN)
b.rawData = arrow.DayTimeIntervalTraits.CastFromBytes(b.data.Bytes())
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *DayTimeIntervalBuilder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *DayTimeIntervalBuilder) Resize(n int) {
nBuilder := n
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(nBuilder, b.init)
b.data.Resize(arrow.DayTimeIntervalTraits.BytesRequired(n))
b.rawData = arrow.DayTimeIntervalTraits.CastFromBytes(b.data.Bytes())
}
}
// NewArray creates a DayTimeInterval array from the memory buffers used by the builder and resets the DayTimeIntervalBuilder
// so it can be used to build a new array.
func (b *DayTimeIntervalBuilder) NewArray() Interface {
return b.NewDayTimeIntervalArray()
}
// NewDayTimeIntervalArray creates a DayTimeInterval array from the memory buffers used by the builder and resets the DayTimeIntervalBuilder
// so it can be used to build a new array.
func (b *DayTimeIntervalBuilder) NewDayTimeIntervalArray() (a *DayTimeInterval) {
data := b.newData()
a = NewDayTimeIntervalData(data)
data.Release()
return
}
func (b *DayTimeIntervalBuilder) newData() (data *Data) {
bytesRequired := arrow.DayTimeIntervalTraits.BytesRequired(b.length)
if bytesRequired > 0 && bytesRequired < b.data.Len() {
// trim buffers
b.data.Resize(bytesRequired)
}
data = NewData(arrow.FixedWidthTypes.DayTimeInterval, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
b.reset()
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
return
}
var (
_ Interface = (*MonthInterval)(nil)
_ Interface = (*DayTimeInterval)(nil)
_ Builder = (*MonthIntervalBuilder)(nil)
_ Builder = (*DayTimeIntervalBuilder)(nil)
)

View File

@@ -1,264 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"strings"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// List represents an immutable sequence of array values.
type List struct {
array
values Interface
offsets []int32
}
// NewListData returns a new List array value, from data.
func NewListData(data *Data) *List {
a := &List{}
a.refCount = 1
a.setData(data)
return a
}
func (a *List) ListValues() Interface { return a.values }
func (a *List) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i := 0; i < a.Len(); i++ {
if i > 0 {
o.WriteString(" ")
}
if !a.IsValid(i) {
o.WriteString("(null)")
continue
}
sub := a.newListValue(i)
fmt.Fprintf(o, "%v", sub)
sub.Release()
}
o.WriteString("]")
return o.String()
}
func (a *List) newListValue(i int) Interface {
j := i + a.array.data.offset
beg := int64(a.offsets[j])
end := int64(a.offsets[j+1])
return NewSlice(a.values, beg, end)
}
func (a *List) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.offsets = arrow.Int32Traits.CastFromBytes(vals.Bytes())
}
a.values = MakeFromData(data.childData[0])
}
func arrayEqualList(left, right *List) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
o := func() bool {
l := left.newListValue(i)
defer l.Release()
r := right.newListValue(i)
defer r.Release()
return ArrayEqual(l, r)
}()
if !o {
return false
}
}
return true
}
// Len returns the number of elements in the array.
func (a *List) Len() int { return a.array.Len() }
func (a *List) Offsets() []int32 { return a.offsets }
func (a *List) Retain() {
a.array.Retain()
a.values.Retain()
}
func (a *List) Release() {
a.array.Release()
a.values.Release()
}
type ListBuilder struct {
builder
etype arrow.DataType // data type of the list's elements.
values Builder // value builder for the list's elements.
offsets *Int32Builder
}
// NewListBuilder returns a builder, using the provided memory allocator.
// The created list builder will create a list whose elements will be of type etype.
func NewListBuilder(mem memory.Allocator, etype arrow.DataType) *ListBuilder {
return &ListBuilder{
builder: builder{refCount: 1, mem: mem},
etype: etype,
values: newBuilder(mem, etype),
offsets: NewInt32Builder(mem),
}
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *ListBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
}
b.values.Release()
b.offsets.Release()
}
func (b *ListBuilder) appendNextOffset() {
b.offsets.Append(int32(b.values.Len()))
}
func (b *ListBuilder) Append(v bool) {
b.Reserve(1)
b.unsafeAppendBoolToBitmap(v)
b.appendNextOffset()
}
func (b *ListBuilder) AppendNull() {
b.Reserve(1)
b.unsafeAppendBoolToBitmap(false)
b.appendNextOffset()
}
func (b *ListBuilder) AppendValues(offsets []int32, valid []bool) {
b.Reserve(len(valid))
b.offsets.AppendValues(offsets, nil)
b.builder.unsafeAppendBoolsToBitmap(valid, len(valid))
}
func (b *ListBuilder) unsafeAppend(v bool) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
b.length++
}
func (b *ListBuilder) unsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
func (b *ListBuilder) init(capacity int) {
b.builder.init(capacity)
b.offsets.init(capacity + 1)
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *ListBuilder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *ListBuilder) Resize(n int) {
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(n, b.builder.init)
b.offsets.resize(n+1, b.offsets.init)
}
}
func (b *ListBuilder) ValueBuilder() Builder {
return b.values
}
// NewArray creates a List array from the memory buffers used by the builder and resets the ListBuilder
// so it can be used to build a new array.
func (b *ListBuilder) NewArray() Interface {
return b.NewListArray()
}
// NewListArray creates a List array from the memory buffers used by the builder and resets the ListBuilder
// so it can be used to build a new array.
func (b *ListBuilder) NewListArray() (a *List) {
if b.offsets.Len() != b.length+1 {
b.appendNextOffset()
}
data := b.newData()
a = NewListData(data)
data.Release()
return
}
func (b *ListBuilder) newData() (data *Data) {
values := b.values.NewArray()
defer values.Release()
var offsets *memory.Buffer
if b.offsets != nil {
arr := b.offsets.NewInt32Array()
defer arr.Release()
offsets = arr.Data().buffers[1]
}
data = NewData(
arrow.ListOf(b.etype), b.length,
[]*memory.Buffer{
b.nullBitmap,
offsets,
},
[]*Data{values.Data()},
b.nulls,
0,
)
b.reset()
return
}
var (
_ Interface = (*List)(nil)
_ Builder = (*ListBuilder)(nil)
)

View File

@@ -1,126 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// Null represents an immutable, degenerate array with no physical storage.
type Null struct {
array
}
// NewNull returns a new Null array value of size n.
func NewNull(n int) *Null {
a := &Null{}
a.refCount = 1
data := NewData(
arrow.Null, n,
[]*memory.Buffer{nil},
nil,
n,
0,
)
a.setData(data)
data.Release()
return a
}
// NewNullData returns a new Null array value, from data.
func NewNullData(data *Data) *Null {
a := &Null{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Null) setData(data *Data) {
a.array.setData(data)
a.array.nullBitmapBytes = nil
a.array.data.nulls = a.array.data.length
}
type NullBuilder struct {
builder
}
// NewNullBuilder returns a builder, using the provided memory allocator.
func NewNullBuilder(mem memory.Allocator) *NullBuilder {
return &NullBuilder{builder: builder{refCount: 1, mem: mem}}
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *NullBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
}
}
func (b *NullBuilder) AppendNull() {
b.builder.length++
b.builder.nulls++
}
func (*NullBuilder) Reserve(size int) {}
func (*NullBuilder) Resize(size int) {}
func (*NullBuilder) init(cap int) {}
func (*NullBuilder) resize(newBits int, init func(int)) {}
// NewArray creates a Null array from the memory buffers used by the builder and resets the NullBuilder
// so it can be used to build a new array.
func (b *NullBuilder) NewArray() Interface {
return b.NewNullArray()
}
// NewNullArray creates a Null array from the memory buffers used by the builder and resets the NullBuilder
// so it can be used to build a new array.
func (b *NullBuilder) NewNullArray() (a *Null) {
data := b.newData()
a = NewNullData(data)
data.Release()
return
}
func (b *NullBuilder) newData() (data *Data) {
data = NewData(
arrow.Null, b.length,
[]*memory.Buffer{nil},
nil,
b.nulls,
0,
)
b.reset()
return
}
var (
_ Interface = (*Null)(nil)
_ Builder = (*NullBuilder)(nil)
)

View File

@@ -1,938 +0,0 @@
// Code generated by array/numeric.gen.go.tmpl. DO NOT EDIT.
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"strings"
"github.com/apache/arrow/go/arrow"
)
// A type which represents an immutable sequence of int64 values.
type Int64 struct {
array
values []int64
}
func NewInt64Data(data *Data) *Int64 {
a := &Int64{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Int64) Value(i int) int64 { return a.values[i] }
func (a *Int64) Int64Values() []int64 { return a.values }
func (a *Int64) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Int64) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Int64Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualInt64(left, right *Int64) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of uint64 values.
type Uint64 struct {
array
values []uint64
}
func NewUint64Data(data *Data) *Uint64 {
a := &Uint64{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Uint64) Value(i int) uint64 { return a.values[i] }
func (a *Uint64) Uint64Values() []uint64 { return a.values }
func (a *Uint64) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Uint64) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Uint64Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualUint64(left, right *Uint64) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of float64 values.
type Float64 struct {
array
values []float64
}
func NewFloat64Data(data *Data) *Float64 {
a := &Float64{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Float64) Value(i int) float64 { return a.values[i] }
func (a *Float64) Float64Values() []float64 { return a.values }
func (a *Float64) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Float64) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Float64Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualFloat64(left, right *Float64) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of int32 values.
type Int32 struct {
array
values []int32
}
func NewInt32Data(data *Data) *Int32 {
a := &Int32{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Int32) Value(i int) int32 { return a.values[i] }
func (a *Int32) Int32Values() []int32 { return a.values }
func (a *Int32) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Int32) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Int32Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualInt32(left, right *Int32) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of uint32 values.
type Uint32 struct {
array
values []uint32
}
func NewUint32Data(data *Data) *Uint32 {
a := &Uint32{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Uint32) Value(i int) uint32 { return a.values[i] }
func (a *Uint32) Uint32Values() []uint32 { return a.values }
func (a *Uint32) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Uint32) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Uint32Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualUint32(left, right *Uint32) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of float32 values.
type Float32 struct {
array
values []float32
}
func NewFloat32Data(data *Data) *Float32 {
a := &Float32{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Float32) Value(i int) float32 { return a.values[i] }
func (a *Float32) Float32Values() []float32 { return a.values }
func (a *Float32) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Float32) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Float32Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualFloat32(left, right *Float32) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of int16 values.
type Int16 struct {
array
values []int16
}
func NewInt16Data(data *Data) *Int16 {
a := &Int16{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Int16) Value(i int) int16 { return a.values[i] }
func (a *Int16) Int16Values() []int16 { return a.values }
func (a *Int16) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Int16) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Int16Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualInt16(left, right *Int16) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of uint16 values.
type Uint16 struct {
array
values []uint16
}
func NewUint16Data(data *Data) *Uint16 {
a := &Uint16{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Uint16) Value(i int) uint16 { return a.values[i] }
func (a *Uint16) Uint16Values() []uint16 { return a.values }
func (a *Uint16) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Uint16) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Uint16Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualUint16(left, right *Uint16) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of int8 values.
type Int8 struct {
array
values []int8
}
func NewInt8Data(data *Data) *Int8 {
a := &Int8{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Int8) Value(i int) int8 { return a.values[i] }
func (a *Int8) Int8Values() []int8 { return a.values }
func (a *Int8) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Int8) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Int8Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualInt8(left, right *Int8) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of uint8 values.
type Uint8 struct {
array
values []uint8
}
func NewUint8Data(data *Data) *Uint8 {
a := &Uint8{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Uint8) Value(i int) uint8 { return a.values[i] }
func (a *Uint8) Uint8Values() []uint8 { return a.values }
func (a *Uint8) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Uint8) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Uint8Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualUint8(left, right *Uint8) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of arrow.Timestamp values.
type Timestamp struct {
array
values []arrow.Timestamp
}
func NewTimestampData(data *Data) *Timestamp {
a := &Timestamp{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Timestamp) Value(i int) arrow.Timestamp { return a.values[i] }
func (a *Timestamp) TimestampValues() []arrow.Timestamp { return a.values }
func (a *Timestamp) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Timestamp) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.TimestampTraits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualTimestamp(left, right *Timestamp) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of arrow.Time32 values.
type Time32 struct {
array
values []arrow.Time32
}
func NewTime32Data(data *Data) *Time32 {
a := &Time32{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Time32) Value(i int) arrow.Time32 { return a.values[i] }
func (a *Time32) Time32Values() []arrow.Time32 { return a.values }
func (a *Time32) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Time32) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Time32Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualTime32(left, right *Time32) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of arrow.Time64 values.
type Time64 struct {
array
values []arrow.Time64
}
func NewTime64Data(data *Data) *Time64 {
a := &Time64{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Time64) Value(i int) arrow.Time64 { return a.values[i] }
func (a *Time64) Time64Values() []arrow.Time64 { return a.values }
func (a *Time64) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Time64) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Time64Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualTime64(left, right *Time64) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of arrow.Date32 values.
type Date32 struct {
array
values []arrow.Date32
}
func NewDate32Data(data *Data) *Date32 {
a := &Date32{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Date32) Value(i int) arrow.Date32 { return a.values[i] }
func (a *Date32) Date32Values() []arrow.Date32 { return a.values }
func (a *Date32) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Date32) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Date32Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualDate32(left, right *Date32) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of arrow.Date64 values.
type Date64 struct {
array
values []arrow.Date64
}
func NewDate64Data(data *Data) *Date64 {
a := &Date64{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Date64) Value(i int) arrow.Date64 { return a.values[i] }
func (a *Date64) Date64Values() []arrow.Date64 { return a.values }
func (a *Date64) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Date64) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.Date64Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualDate64(left, right *Date64) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A type which represents an immutable sequence of arrow.Duration values.
type Duration struct {
array
values []arrow.Duration
}
func NewDurationData(data *Data) *Duration {
a := &Duration{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Duration) Value(i int) arrow.Duration { return a.values[i] }
func (a *Duration) DurationValues() []arrow.Duration { return a.values }
func (a *Duration) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *Duration) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.DurationTraits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqualDuration(left, right *Duration) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}

View File

@@ -1,85 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"strings"
"github.com/apache/arrow/go/arrow"
)
{{range .In}}
// A type which represents an immutable sequence of {{or .QualifiedType .Type}} values.
type {{.Name}} struct {
array
values []{{or .QualifiedType .Type}}
}
func New{{.Name}}Data(data *Data) *{{.Name}} {
a := &{{.Name}}{}
a.refCount = 1
a.setData(data)
return a
}
func (a *{{.Name}}) Value(i int) {{or .QualifiedType .Type}} { return a.values[i] }
func (a *{{.Name}}) {{.Name}}Values() []{{or .QualifiedType .Type}} { return a.values }
func (a *{{.Name}}) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i, v := range a.values {
if i > 0 {
fmt.Fprintf(o, " ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%v", v)
}
}
o.WriteString("]")
return o.String()
}
func (a *{{.Name}}) setData(data *Data) {
a.array.setData(data)
vals := data.buffers[1]
if vals != nil {
a.values = arrow.{{.Name}}Traits.CastFromBytes(vals.Bytes())
beg := a.array.data.offset
end := beg + a.array.data.length
a.values = a.values[beg:end]
}
}
func arrayEqual{{.Name}}(left, right *{{.Name}}) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
{{end}}

File diff suppressed because it is too large Load Diff

View File

@@ -1,182 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
{{range .In}}
type {{.Name}}Builder struct {
builder
{{if .Opt.Parametric -}}
dtype *arrow.{{.Name}}Type
{{end -}}
data *memory.Buffer
rawData []{{or .QualifiedType .Type}}
}
{{if .Opt.Parametric}}
func New{{.Name}}Builder(mem memory.Allocator, dtype *arrow.{{.Name}}Type) *{{.Name}}Builder {
return &{{.Name}}Builder{builder: builder{refCount:1, mem: mem}, dtype: dtype}
}
{{else}}
func New{{.Name}}Builder(mem memory.Allocator) *{{.Name}}Builder {
return &{{.Name}}Builder{builder: builder{refCount:1, mem: mem}}
}
{{end}}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *{{.Name}}Builder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
}
}
func (b *{{.Name}}Builder) Append(v {{or .QualifiedType .Type}}) {
b.Reserve(1)
b.UnsafeAppend(v)
}
func (b *{{.Name}}Builder) AppendNull() {
b.Reserve(1)
b.UnsafeAppendBoolToBitmap(false)
}
func (b *{{.Name}}Builder) UnsafeAppend(v {{or .QualifiedType .Type}}) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
b.rawData[b.length] = v
b.length++
}
func (b *{{.Name}}Builder) UnsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
// AppendValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *{{.Name}}Builder) AppendValues(v []{{or .QualifiedType .Type}}, valid []bool) {
if len(v) != len(valid) && len(valid) != 0 {
panic("len(v) != len(valid) && len(valid) != 0")
}
if len(v) == 0 {
return
}
b.Reserve(len(v))
arrow.{{.Name}}Traits.Copy(b.rawData[b.length:], v)
b.builder.unsafeAppendBoolsToBitmap(valid, len(v))
}
func (b *{{.Name}}Builder) init(capacity int) {
b.builder.init(capacity)
b.data = memory.NewResizableBuffer(b.mem)
bytesN := arrow.{{.Name}}Traits.BytesRequired(capacity)
b.data.Resize(bytesN)
b.rawData = arrow.{{.Name}}Traits.CastFromBytes(b.data.Bytes())
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *{{.Name}}Builder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *{{.Name}}Builder) Resize(n int) {
nBuilder := n
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(nBuilder, b.init)
b.data.Resize(arrow.{{.Name}}Traits.BytesRequired(n))
b.rawData = arrow.{{.Name}}Traits.CastFromBytes(b.data.Bytes())
}
}
// NewArray creates a {{.Name}} array from the memory buffers used by the builder and resets the {{.Name}}Builder
// so it can be used to build a new array.
func (b *{{.Name}}Builder) NewArray() Interface {
return b.New{{.Name}}Array()
}
// New{{.Name}}Array creates a {{.Name}} array from the memory buffers used by the builder and resets the {{.Name}}Builder
// so it can be used to build a new array.
func (b *{{.Name}}Builder) New{{.Name}}Array() (a *{{.Name}}) {
data := b.newData()
a = New{{.Name}}Data(data)
data.Release()
return
}
func (b *{{.Name}}Builder) newData() (data *Data) {
bytesRequired := arrow.{{.Name}}Traits.BytesRequired(b.length)
if bytesRequired > 0 && bytesRequired < b.data.Len() {
// trim buffers
b.data.Resize(bytesRequired)
}
{{if .Opt.Parametric -}}
data = NewData(b.dtype, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
{{else -}}
data = NewData(arrow.PrimitiveTypes.{{.Name}}, b.length, []*memory.Buffer{b.nullBitmap, b.data}, nil, b.nulls, 0)
{{end -}}
b.reset()
if b.data != nil {
b.data.Release()
b.data = nil
b.rawData = nil
}
return
}
{{end}}
var (
{{- range .In}}
_ Builder = (*{{.Name}}Builder)(nil)
{{- end}}
)

View File

@@ -1,216 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array_test
import (
"testing"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/array"
"github.com/apache/arrow/go/arrow/memory"
"github.com/stretchr/testify/assert"
)
{{range .In}}
func TestNew{{.Name}}Builder(t *testing.T) {
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
{{if .Opt.Parametric -}}
dtype := &arrow.{{.Name}}Type{Unit: arrow.Second}
ab := array.New{{.Name}}Builder(mem, dtype)
{{else}}
ab := array.New{{.Name}}Builder(mem)
{{end -}}
defer ab.Release()
ab.Retain()
ab.Release()
ab.Append(1)
ab.Append(2)
ab.Append(3)
ab.AppendNull()
ab.Append(5)
ab.Append(6)
ab.AppendNull()
ab.Append(8)
ab.Append(9)
ab.Append(10)
// check state of builder before New{{.Name}}Array
assert.Equal(t, 10, ab.Len(), "unexpected Len()")
assert.Equal(t, 2, ab.NullN(), "unexpected NullN()")
a := ab.New{{.Name}}Array()
// check state of builder after New{{.Name}}Array
assert.Zero(t, ab.Len(), "unexpected ArrayBuilder.Len(), New{{.Name}}Array did not reset state")
assert.Zero(t, ab.Cap(), "unexpected ArrayBuilder.Cap(), New{{.Name}}Array did not reset state")
assert.Zero(t, ab.NullN(), "unexpected ArrayBuilder.NullN(), New{{.Name}}Array did not reset state")
// check state of array
assert.Equal(t, 2, a.NullN(), "unexpected null count")
assert.Equal(t, []{{or .QualifiedType .Type}}{1, 2, 3, 0, 5, 6, 0, 8, 9, 10}, a.{{.Name}}Values(), "unexpected {{.Name}}Values")
assert.Equal(t, []byte{0xb7}, a.NullBitmapBytes()[:1]) // 4 bytes due to minBuilderCapacity
assert.Len(t, a.{{.Name}}Values(), 10, "unexpected length of {{.Name}}Values")
a.Release()
ab.Append(7)
ab.Append(8)
a = ab.New{{.Name}}Array()
assert.Equal(t, 0, a.NullN())
assert.Equal(t, []{{or .QualifiedType .Type}}{7, 8}, a.{{.Name}}Values())
assert.Len(t, a.{{.Name}}Values(), 2)
a.Release()
var (
want = []{{or .QualifiedType .Type}}{1, 2, 3, 4}
valids = []bool{true, true, false, true}
)
ab.AppendValues(want, valids)
a = ab.New{{.Name}}Array()
sub := array.MakeFromData(a.Data())
defer sub.Release()
if got, want := sub.DataType().ID(), a.DataType().ID(); got != want {
t.Fatalf("invalid type: got=%q, want=%q", got, want)
}
if _, ok := sub.(*array.{{.Name}}); !ok {
t.Fatalf("could not type-assert to array.{{.Name}}")
}
if got, want := a.String(), `[1 2 (null) 4]`; got != want {
t.Fatalf("got=%q, want=%q", got, want)
}
slice := array.NewSliceData(a.Data(), 2, 4)
defer slice.Release()
sub1 := array.MakeFromData(slice)
defer sub1.Release()
v, ok := sub1.(*array.{{.Name}})
if !ok {
t.Fatalf("could not type-assert to array.{{.Name}}")
}
if got, want := v.String(), `[(null) 4]`; got != want {
t.Fatalf("got=%q, want=%q", got, want)
}
a.Release()
}
func Test{{.Name}}Builder_AppendValues(t *testing.T) {
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
{{if .Opt.Parametric -}}
dtype := &arrow.{{.Name}}Type{Unit: arrow.Second}
ab := array.New{{.Name}}Builder(mem, dtype)
{{else}}
ab := array.New{{.Name}}Builder(mem)
{{end -}}
defer ab.Release()
exp := []{{or .QualifiedType .Type}}{0, 1, 2, 3}
ab.AppendValues(exp, nil)
a := ab.New{{.Name}}Array()
assert.Equal(t, exp, a.{{.Name}}Values())
a.Release()
}
func Test{{.Name}}Builder_Empty(t *testing.T) {
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
{{if .Opt.Parametric -}}
dtype := &arrow.{{.Name}}Type{Unit: arrow.Second}
ab := array.New{{.Name}}Builder(mem, dtype)
{{else}}
ab := array.New{{.Name}}Builder(mem)
{{end -}}
defer ab.Release()
exp := []{{or .QualifiedType .Type}}{0, 1, 2, 3}
ab.AppendValues([]{{or .QualifiedType .Type}}{}, nil)
a := ab.New{{.Name}}Array()
assert.Zero(t, a.Len())
a.Release()
ab.AppendValues(nil, nil)
a = ab.New{{.Name}}Array()
assert.Zero(t, a.Len())
a.Release()
ab.AppendValues([]{{or .QualifiedType .Type}}{}, nil)
ab.AppendValues(exp, nil)
a = ab.New{{.Name}}Array()
assert.Equal(t, exp, a.{{.Name}}Values())
a.Release()
ab.AppendValues(exp, nil)
ab.AppendValues([]{{or .QualifiedType .Type}}{}, nil)
a = ab.New{{.Name}}Array()
assert.Equal(t, exp, a.{{.Name}}Values())
a.Release()
}
func Test{{.Name}}Builder_Resize(t *testing.T) {
mem := memory.NewCheckedAllocator(memory.NewGoAllocator())
defer mem.AssertSize(t, 0)
{{if .Opt.Parametric -}}
dtype := &arrow.{{.Name}}Type{Unit: arrow.Second}
ab := array.New{{.Name}}Builder(mem, dtype)
{{else}}
ab := array.New{{.Name}}Builder(mem)
{{end -}}
defer ab.Release()
assert.Equal(t, 0, ab.Cap())
assert.Equal(t, 0, ab.Len())
ab.Reserve(63)
assert.Equal(t, 64, ab.Cap())
assert.Equal(t, 0, ab.Len())
for i := 0; i < 63; i++ {
ab.Append(0)
}
assert.Equal(t, 64, ab.Cap())
assert.Equal(t, 63, ab.Len())
ab.Resize(5)
assert.Equal(t, 5, ab.Len())
ab.Resize(32)
assert.Equal(t, 5, ab.Len())
}
{{end}}

View File

@@ -1,345 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"strings"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// RecordReader reads a stream of records.
type RecordReader interface {
Retain()
Release()
Schema() *arrow.Schema
Next() bool
Record() Record
}
// simpleRecords is a simple iterator over a collection of records.
type simpleRecords struct {
refCount int64
schema *arrow.Schema
recs []Record
cur Record
}
// NewRecordReader returns a simple iterator over the given slice of records.
func NewRecordReader(schema *arrow.Schema, recs []Record) (*simpleRecords, error) {
rs := &simpleRecords{
refCount: 1,
schema: schema,
recs: recs,
cur: nil,
}
for _, rec := range rs.recs {
rec.Retain()
}
for _, rec := range recs {
if !rec.Schema().Equal(rs.schema) {
rs.Release()
return nil, fmt.Errorf("arrow/array: mismatch schema")
}
}
return rs, nil
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (rs *simpleRecords) Retain() {
atomic.AddInt64(&rs.refCount, 1)
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (rs *simpleRecords) Release() {
debug.Assert(atomic.LoadInt64(&rs.refCount) > 0, "too many releases")
if atomic.AddInt64(&rs.refCount, -1) == 0 {
if rs.cur != nil {
rs.cur.Release()
}
for _, rec := range rs.recs {
rec.Release()
}
rs.recs = nil
}
}
func (rs *simpleRecords) Schema() *arrow.Schema { return rs.schema }
func (rs *simpleRecords) Record() Record { return rs.cur }
func (rs *simpleRecords) Next() bool {
if len(rs.recs) == 0 {
return false
}
if rs.cur != nil {
rs.cur.Release()
}
rs.cur = rs.recs[0]
rs.recs = rs.recs[1:]
return true
}
// Record is a collection of equal-length arrays
// matching a particular Schema.
type Record interface {
Release()
Retain()
Schema() *arrow.Schema
NumRows() int64
NumCols() int64
Columns() []Interface
Column(i int) Interface
ColumnName(i int) string
// NewSlice constructs a zero-copy slice of the record with the indicated
// indices i and j, corresponding to array[i:j].
// The returned record must be Release()'d after use.
//
// NewSlice panics if the slice is outside the valid range of the record array.
// NewSlice panics if j < i.
NewSlice(i, j int64) Record
}
// simpleRecord is a basic, non-lazy in-memory record batch.
type simpleRecord struct {
refCount int64
schema *arrow.Schema
rows int64
arrs []Interface
}
// NewRecord returns a basic, non-lazy in-memory record batch.
//
// NewRecord panics if the columns and schema are inconsistent.
// NewRecord panics if rows is larger than the height of the columns.
func NewRecord(schema *arrow.Schema, cols []Interface, nrows int64) *simpleRecord {
rec := &simpleRecord{
refCount: 1,
schema: schema,
rows: nrows,
arrs: make([]Interface, len(cols)),
}
copy(rec.arrs, cols)
for _, arr := range rec.arrs {
arr.Retain()
}
if rec.rows < 0 {
switch len(rec.arrs) {
case 0:
rec.rows = 0
default:
rec.rows = int64(rec.arrs[0].Len())
}
}
err := rec.validate()
if err != nil {
rec.Release()
panic(err)
}
return rec
}
func (rec *simpleRecord) validate() error {
if len(rec.arrs) != len(rec.schema.Fields()) {
return fmt.Errorf("arrow/array: number of columns/fields mismatch")
}
for i, arr := range rec.arrs {
f := rec.schema.Field(i)
if int64(arr.Len()) < rec.rows {
return fmt.Errorf("arrow/array: mismatch number of rows in column %q: got=%d, want=%d",
f.Name,
arr.Len(), rec.rows,
)
}
if !arrow.TypeEquals(f.Type, arr.DataType()) {
return fmt.Errorf("arrow/array: column %q type mismatch: got=%v, want=%v",
f.Name,
arr.DataType(), f.Type,
)
}
}
return nil
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (rec *simpleRecord) Retain() {
atomic.AddInt64(&rec.refCount, 1)
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (rec *simpleRecord) Release() {
debug.Assert(atomic.LoadInt64(&rec.refCount) > 0, "too many releases")
if atomic.AddInt64(&rec.refCount, -1) == 0 {
for _, arr := range rec.arrs {
arr.Release()
}
rec.arrs = nil
}
}
func (rec *simpleRecord) Schema() *arrow.Schema { return rec.schema }
func (rec *simpleRecord) NumRows() int64 { return rec.rows }
func (rec *simpleRecord) NumCols() int64 { return int64(len(rec.arrs)) }
func (rec *simpleRecord) Columns() []Interface { return rec.arrs }
func (rec *simpleRecord) Column(i int) Interface { return rec.arrs[i] }
func (rec *simpleRecord) ColumnName(i int) string { return rec.schema.Field(i).Name }
// NewSlice constructs a zero-copy slice of the record with the indicated
// indices i and j, corresponding to array[i:j].
// The returned record must be Release()'d after use.
//
// NewSlice panics if the slice is outside the valid range of the record array.
// NewSlice panics if j < i.
func (rec *simpleRecord) NewSlice(i, j int64) Record {
arrs := make([]Interface, len(rec.arrs))
for ii, arr := range rec.arrs {
arrs[ii] = NewSlice(arr, i, j)
}
defer func() {
for _, arr := range arrs {
arr.Release()
}
}()
return NewRecord(rec.schema, arrs, j-i)
}
func (rec *simpleRecord) String() string {
o := new(strings.Builder)
fmt.Fprintf(o, "record:\n %v\n", rec.schema)
fmt.Fprintf(o, " rows: %d\n", rec.rows)
for i, col := range rec.arrs {
fmt.Fprintf(o, " col[%d][%s]: %v\n", i, rec.schema.Field(i).Name, col)
}
return o.String()
}
// RecordBuilder eases the process of building a Record, iteratively, from
// a known Schema.
type RecordBuilder struct {
refCount int64
mem memory.Allocator
schema *arrow.Schema
fields []Builder
}
// NewRecordBuilder returns a builder, using the provided memory allocator and a schema.
func NewRecordBuilder(mem memory.Allocator, schema *arrow.Schema) *RecordBuilder {
b := &RecordBuilder{
refCount: 1,
mem: mem,
schema: schema,
fields: make([]Builder, len(schema.Fields())),
}
for i, f := range schema.Fields() {
b.fields[i] = newBuilder(b.mem, f.Type)
}
return b
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (b *RecordBuilder) Retain() {
atomic.AddInt64(&b.refCount, 1)
}
// Release decreases the reference count by 1.
func (b *RecordBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
for _, f := range b.fields {
f.Release()
}
if atomic.AddInt64(&b.refCount, -1) == 0 {
b.fields = nil
}
}
func (b *RecordBuilder) Schema() *arrow.Schema { return b.schema }
func (b *RecordBuilder) Fields() []Builder { return b.fields }
func (b *RecordBuilder) Field(i int) Builder { return b.fields[i] }
func (b *RecordBuilder) Reserve(size int) {
for _, f := range b.fields {
f.Reserve(size)
}
}
// NewRecord creates a new record from the memory buffers and resets the
// RecordBuilder so it can be used to build a new record.
//
// The returned Record must be Release()'d after use.
//
// NewRecord panics if the fields' builder do not have the same length.
func (b *RecordBuilder) NewRecord() Record {
cols := make([]Interface, len(b.fields))
rows := int64(0)
defer func(cols []Interface) {
for _, col := range cols {
if col == nil {
continue
}
col.Release()
}
}(cols)
for i, f := range b.fields {
cols[i] = f.NewArray()
irow := int64(cols[i].Len())
if i > 0 && irow != rows {
panic(fmt.Errorf("arrow/array: field %d has %d rows. want=%d", i, irow, rows))
}
rows = irow
}
return NewRecord(b.schema, cols, rows)
}
var (
_ Record = (*simpleRecord)(nil)
_ RecordReader = (*simpleRecords)(nil)
)

View File

@@ -1,194 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"math"
"strings"
"unsafe"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/memory"
)
const (
stringArrayMaximumCapacity = math.MaxInt32
)
// A type which represents an immutable sequence of variable-length UTF-8 strings.
type String struct {
array
offsets []int32
values string
}
// NewStringData constructs a new String array from data.
func NewStringData(data *Data) *String {
a := &String{}
a.refCount = 1
a.setData(data)
return a
}
// Value returns the slice at index i. This value should not be mutated.
func (a *String) Value(i int) string {
i = i + a.array.data.offset
return a.values[a.offsets[i]:a.offsets[i+1]]
}
func (a *String) ValueOffset(i int) int { return int(a.offsets[i]) }
func (a *String) String() string {
o := new(strings.Builder)
o.WriteString("[")
for i := 0; i < a.Len(); i++ {
if i > 0 {
o.WriteString(" ")
}
switch {
case a.IsNull(i):
o.WriteString("(null)")
default:
fmt.Fprintf(o, "%q", a.Value(i))
}
}
o.WriteString("]")
return o.String()
}
func (a *String) setData(data *Data) {
if len(data.buffers) != 3 {
panic("arrow/array: len(data.buffers) != 3")
}
a.array.setData(data)
if vdata := data.buffers[2]; vdata != nil {
b := vdata.Bytes()
a.values = *(*string)(unsafe.Pointer(&b))
}
if offsets := data.buffers[1]; offsets != nil {
a.offsets = arrow.Int32Traits.CastFromBytes(offsets.Bytes())
}
}
func arrayEqualString(left, right *String) bool {
for i := 0; i < left.Len(); i++ {
if left.IsNull(i) {
continue
}
if left.Value(i) != right.Value(i) {
return false
}
}
return true
}
// A StringBuilder is used to build a String array using the Append methods.
type StringBuilder struct {
builder *BinaryBuilder
}
func NewStringBuilder(mem memory.Allocator) *StringBuilder {
b := &StringBuilder{
builder: NewBinaryBuilder(mem, arrow.BinaryTypes.String),
}
return b
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (b *StringBuilder) Release() {
b.builder.Release()
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (b *StringBuilder) Retain() {
b.builder.Retain()
}
//
// Len returns the number of elements in the array builder.
func (b *StringBuilder) Len() int { return b.builder.Len() }
// Cap returns the total number of elements that can be stored without allocating additional memory.
func (b *StringBuilder) Cap() int { return b.builder.Cap() }
// NullN returns the number of null values in the array builder.
func (b *StringBuilder) NullN() int { return b.builder.NullN() }
func (b *StringBuilder) Append(v string) {
b.builder.Append([]byte(v))
}
func (b *StringBuilder) AppendNull() {
b.builder.AppendNull()
}
// AppendValues will append the values in the v slice. The valid slice determines which values
// in v are valid (not null). The valid slice must either be empty or be equal in length to v. If empty,
// all values in v are appended and considered valid.
func (b *StringBuilder) AppendValues(v []string, valid []bool) {
b.builder.AppendStringValues(v, valid)
}
func (b *StringBuilder) Value(i int) string {
return string(b.builder.Value(i))
}
func (b *StringBuilder) init(capacity int) {
b.builder.init(capacity)
}
func (b *StringBuilder) resize(newBits int, init func(int)) {
b.builder.resize(newBits, init)
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *StringBuilder) Reserve(n int) {
b.builder.Reserve(n)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *StringBuilder) Resize(n int) {
b.builder.Resize(n)
}
// NewArray creates a String array from the memory buffers used by the builder and resets the StringBuilder
// so it can be used to build a new array.
func (b *StringBuilder) NewArray() Interface {
return b.NewStringArray()
}
// NewStringArray creates a String array from the memory buffers used by the builder and resets the StringBuilder
// so it can be used to build a new array.
func (b *StringBuilder) NewStringArray() (a *String) {
data := b.builder.newData()
a = NewStringData(data)
data.Release()
return
}
var (
_ Interface = (*String)(nil)
_ Builder = (*StringBuilder)(nil)
)

View File

@@ -1,234 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"fmt"
"strings"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/bitutil"
"github.com/apache/arrow/go/arrow/internal/debug"
"github.com/apache/arrow/go/arrow/memory"
)
// Struct represents an ordered sequence of relative types.
type Struct struct {
array
fields []Interface
}
// NewStructData returns a new Struct array value from data.
func NewStructData(data *Data) *Struct {
a := &Struct{}
a.refCount = 1
a.setData(data)
return a
}
func (a *Struct) NumField() int { return len(a.fields) }
func (a *Struct) Field(i int) Interface { return a.fields[i] }
func (a *Struct) String() string {
o := new(strings.Builder)
o.WriteString("{")
for i, v := range a.fields {
if i > 0 {
o.WriteString(" ")
}
fmt.Fprintf(o, "%v", v)
}
o.WriteString("}")
return o.String()
}
func (a *Struct) setData(data *Data) {
a.array.setData(data)
a.fields = make([]Interface, len(data.childData))
for i, child := range data.childData {
a.fields[i] = MakeFromData(child)
}
}
func arrayEqualStruct(left, right *Struct) bool {
for i, lf := range left.fields {
rf := right.fields[i]
if !ArrayEqual(lf, rf) {
return false
}
}
return true
}
func (a *Struct) Retain() {
a.array.Retain()
for _, f := range a.fields {
f.Retain()
}
}
func (a *Struct) Release() {
a.array.Release()
for _, f := range a.fields {
f.Release()
}
}
type StructBuilder struct {
builder
dtype arrow.DataType
fields []Builder
}
// NewStructBuilder returns a builder, using the provided memory allocator.
func NewStructBuilder(mem memory.Allocator, dtype *arrow.StructType) *StructBuilder {
b := &StructBuilder{
builder: builder{refCount: 1, mem: mem},
dtype: dtype,
fields: make([]Builder, len(dtype.Fields())),
}
for i, f := range dtype.Fields() {
b.fields[i] = newBuilder(b.mem, f.Type)
}
return b
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
func (b *StructBuilder) Release() {
debug.Assert(atomic.LoadInt64(&b.refCount) > 0, "too many releases")
if atomic.AddInt64(&b.refCount, -1) == 0 {
if b.nullBitmap != nil {
b.nullBitmap.Release()
b.nullBitmap = nil
}
}
for _, f := range b.fields {
f.Release()
}
}
func (b *StructBuilder) Append(v bool) {
b.Reserve(1)
b.unsafeAppendBoolToBitmap(v)
if !v {
for _, f := range b.fields {
f.AppendNull()
}
}
}
func (b *StructBuilder) AppendValues(valids []bool) {
b.Reserve(len(valids))
b.builder.unsafeAppendBoolsToBitmap(valids, len(valids))
}
func (b *StructBuilder) AppendNull() { b.Append(false) }
func (b *StructBuilder) unsafeAppend(v bool) {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
b.length++
}
func (b *StructBuilder) unsafeAppendBoolToBitmap(isValid bool) {
if isValid {
bitutil.SetBit(b.nullBitmap.Bytes(), b.length)
} else {
b.nulls++
}
b.length++
}
func (b *StructBuilder) init(capacity int) {
b.builder.init(capacity)
for _, f := range b.fields {
f.init(capacity)
}
}
// Reserve ensures there is enough space for appending n elements
// by checking the capacity and calling Resize if necessary.
func (b *StructBuilder) Reserve(n int) {
b.builder.reserve(n, b.Resize)
}
// Resize adjusts the space allocated by b to n elements. If n is greater than b.Cap(),
// additional memory will be allocated. If n is smaller, the allocated memory may reduced.
func (b *StructBuilder) Resize(n int) {
if n < minBuilderCapacity {
n = minBuilderCapacity
}
if b.capacity == 0 {
b.init(n)
} else {
b.builder.resize(n, b.builder.init)
for _, f := range b.fields {
f.resize(n, f.init)
}
}
}
func (b *StructBuilder) NumField() int { return len(b.fields) }
func (b *StructBuilder) FieldBuilder(i int) Builder { return b.fields[i] }
// NewArray creates a Struct array from the memory buffers used by the builder and resets the StructBuilder
// so it can be used to build a new array.
func (b *StructBuilder) NewArray() Interface {
return b.NewStructArray()
}
// NewStructArray creates a Struct array from the memory buffers used by the builder and resets the StructBuilder
// so it can be used to build a new array.
func (b *StructBuilder) NewStructArray() (a *Struct) {
data := b.newData()
a = NewStructData(data)
data.Release()
return
}
func (b *StructBuilder) newData() (data *Data) {
fields := make([]*Data, len(b.fields))
for i, f := range b.fields {
arr := f.NewArray()
defer arr.Release()
fields[i] = arr.Data()
}
data = NewData(
b.dtype, b.length,
[]*memory.Buffer{
b.nullBitmap,
nil, // FIXME(sbinet)
},
fields,
b.nulls,
0,
)
b.reset()
return
}
var (
_ Interface = (*Struct)(nil)
_ Builder = (*StructBuilder)(nil)
)

View File

@@ -1,455 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
import (
"errors"
"fmt"
"math"
"sync/atomic"
"github.com/apache/arrow/go/arrow"
"github.com/apache/arrow/go/arrow/internal/debug"
)
// Table represents a logical sequence of chunked arrays.
type Table interface {
Schema() *arrow.Schema
NumRows() int64
NumCols() int64
Column(i int) *Column
Retain()
Release()
}
// Column is an immutable column data structure consisting of
// a field (type metadata) and a chunked data array.
type Column struct {
field arrow.Field
data *Chunked
}
// NewColumn returns a column from a field and a chunked data array.
//
// NewColumn panics if the field's data type is inconsistent with the data type
// of the chunked data array.
func NewColumn(field arrow.Field, chunks *Chunked) *Column {
col := Column{
field: field,
data: chunks,
}
col.data.Retain()
if !arrow.TypeEquals(col.data.DataType(), col.field.Type) {
col.data.Release()
panic("arrow/array: inconsistent data type")
}
return &col
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (col *Column) Retain() {
col.data.Retain()
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (col *Column) Release() {
col.data.Release()
}
func (col *Column) Len() int { return col.data.Len() }
func (col *Column) NullN() int { return col.data.NullN() }
func (col *Column) Data() *Chunked { return col.data }
func (col *Column) Field() arrow.Field { return col.field }
func (col *Column) Name() string { return col.field.Name }
func (col *Column) DataType() arrow.DataType { return col.field.Type }
// NewSlice returns a new zero-copy slice of the column with the indicated
// indices i and j, corresponding to the column's array[i:j].
// The returned column must be Release()'d after use.
//
// NewSlice panics if the slice is outside the valid range of the column's array.
// NewSlice panics if j < i.
func (col *Column) NewSlice(i, j int64) *Column {
return &Column{
field: col.field,
data: col.data.NewSlice(i, j),
}
}
// Chunked manages a collection of primitives arrays as one logical large array.
type Chunked struct {
chunks []Interface
refCount int64
length int
nulls int
dtype arrow.DataType
}
// NewChunked returns a new chunked array from the slice of arrays.
//
// NewChunked panics if the chunks do not have the same data type.
func NewChunked(dtype arrow.DataType, chunks []Interface) *Chunked {
arr := &Chunked{
chunks: make([]Interface, len(chunks)),
refCount: 1,
dtype: dtype,
}
for i, chunk := range chunks {
if !arrow.TypeEquals(chunk.DataType(), dtype) {
panic("arrow/array: mismatch data type")
}
chunk.Retain()
arr.chunks[i] = chunk
arr.length += chunk.Len()
arr.nulls += chunk.NullN()
}
return arr
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (a *Chunked) Retain() {
atomic.AddInt64(&a.refCount, 1)
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (a *Chunked) Release() {
debug.Assert(atomic.LoadInt64(&a.refCount) > 0, "too many releases")
if atomic.AddInt64(&a.refCount, -1) == 0 {
for _, arr := range a.chunks {
arr.Release()
}
a.chunks = nil
a.length = 0
a.nulls = 0
}
}
func (a *Chunked) Len() int { return a.length }
func (a *Chunked) NullN() int { return a.nulls }
func (a *Chunked) DataType() arrow.DataType { return a.dtype }
func (a *Chunked) Chunks() []Interface { return a.chunks }
func (a *Chunked) Chunk(i int) Interface { return a.chunks[i] }
// NewSlice constructs a zero-copy slice of the chunked array with the indicated
// indices i and j, corresponding to array[i:j].
// The returned chunked array must be Release()'d after use.
//
// NewSlice panics if the slice is outside the valid range of the input array.
// NewSlice panics if j < i.
func (a *Chunked) NewSlice(i, j int64) *Chunked {
if j > int64(a.length) || i > j || i > int64(a.length) {
panic("arrow/array: index out of range")
}
var (
cur = 0
beg = i
sz = j - i
chunks = make([]Interface, 0, len(a.chunks))
)
for cur < len(a.chunks) && beg >= int64(a.chunks[cur].Len()) {
beg -= int64(a.chunks[cur].Len())
cur++
}
for cur < len(a.chunks) && sz > 0 {
arr := a.chunks[cur]
end := beg + sz
if end > int64(arr.Len()) {
end = int64(arr.Len())
}
chunks = append(chunks, NewSlice(arr, beg, end))
sz -= int64(arr.Len()) - beg
beg = 0
cur++
}
chunks = chunks[:len(chunks):len(chunks)]
defer func() {
for _, chunk := range chunks {
chunk.Release()
}
}()
return NewChunked(a.dtype, chunks)
}
// simpleTable is a basic, non-lazy in-memory table.
type simpleTable struct {
refCount int64
rows int64
cols []Column
schema *arrow.Schema
}
// NewTable returns a new basic, non-lazy in-memory table.
// If rows is negative, the number of rows will be inferred from the height
// of the columns.
//
// NewTable panics if the columns and schema are inconsistent.
// NewTable panics if rows is larger than the height of the columns.
func NewTable(schema *arrow.Schema, cols []Column, rows int64) *simpleTable {
tbl := simpleTable{
refCount: 1,
rows: rows,
cols: cols,
schema: schema,
}
if tbl.rows < 0 {
switch len(tbl.cols) {
case 0:
tbl.rows = 0
default:
tbl.rows = int64(tbl.cols[0].Len())
}
}
// validate the table and its constituents.
// note we retain the columns after having validated the table
// in case the validation fails and panics (and would otherwise leak
// a ref-count on the columns.)
tbl.validate()
for i := range tbl.cols {
tbl.cols[i].Retain()
}
return &tbl
}
// NewTableFromRecords returns a new basic, non-lazy in-memory table.
//
// NewTableFromRecords panics if the records and schema are inconsistent.
func NewTableFromRecords(schema *arrow.Schema, recs []Record) *simpleTable {
arrs := make([]Interface, len(recs))
cols := make([]Column, len(schema.Fields()))
defer func(cols []Column) {
for i := range cols {
cols[i].Release()
}
}(cols)
for i := range cols {
field := schema.Field(i)
for j, rec := range recs {
arrs[j] = rec.Column(i)
}
chunk := NewChunked(field.Type, arrs)
cols[i] = *NewColumn(field, chunk)
chunk.Release()
}
return NewTable(schema, cols, -1)
}
func (tbl *simpleTable) Schema() *arrow.Schema { return tbl.schema }
func (tbl *simpleTable) NumRows() int64 { return tbl.rows }
func (tbl *simpleTable) NumCols() int64 { return int64(len(tbl.cols)) }
func (tbl *simpleTable) Column(i int) *Column { return &tbl.cols[i] }
func (tbl *simpleTable) validate() {
if len(tbl.cols) != len(tbl.schema.Fields()) {
panic(errors.New("arrow/array: table schema mismatch"))
}
for i, col := range tbl.cols {
if !col.field.Equal(tbl.schema.Field(i)) {
panic(fmt.Errorf("arrow/array: column field %q is inconsistent with schema", col.Name()))
}
if int64(col.Len()) < tbl.rows {
panic(fmt.Errorf("arrow/array: column %q expected length >= %d but got length %d", col.Name(), tbl.rows, col.Len()))
}
}
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (tbl *simpleTable) Retain() {
atomic.AddInt64(&tbl.refCount, 1)
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (tbl *simpleTable) Release() {
debug.Assert(atomic.LoadInt64(&tbl.refCount) > 0, "too many releases")
if atomic.AddInt64(&tbl.refCount, -1) == 0 {
for i := range tbl.cols {
tbl.cols[i].Release()
}
tbl.cols = nil
}
}
// TableReader is a Record iterator over a (possibly chunked) Table
type TableReader struct {
refCount int64
tbl Table
cur int64 // current row
max int64 // total number of rows
rec Record // current Record
chksz int64 // chunk size
chunks []*Chunked
slots []int // chunk indices
offsets []int64 // chunk offsets
}
// NewTableReader returns a new TableReader to iterate over the (possibly chunked) Table.
// if chunkSize is <= 0, the biggest possible chunk will be selected.
func NewTableReader(tbl Table, chunkSize int64) *TableReader {
ncols := tbl.NumCols()
tr := &TableReader{
refCount: 1,
tbl: tbl,
cur: 0,
max: int64(tbl.NumRows()),
chksz: chunkSize,
chunks: make([]*Chunked, ncols),
slots: make([]int, ncols),
offsets: make([]int64, ncols),
}
tr.tbl.Retain()
if tr.chksz <= 0 {
tr.chksz = math.MaxInt64
}
for i := range tr.chunks {
col := tr.tbl.Column(i)
tr.chunks[i] = col.Data()
tr.chunks[i].Retain()
}
return tr
}
func (tr *TableReader) Schema() *arrow.Schema { return tr.tbl.Schema() }
func (tr *TableReader) Record() Record { return tr.rec }
func (tr *TableReader) Next() bool {
if tr.cur >= tr.max {
return false
}
if tr.rec != nil {
tr.rec.Release()
}
// determine the minimum contiguous slice across all columns
chunksz := imin64(tr.max, tr.chksz)
chunks := make([]Interface, len(tr.chunks))
for i := range chunks {
j := tr.slots[i]
chunk := tr.chunks[i].Chunk(j)
remain := int64(chunk.Len()) - tr.offsets[i]
if remain < chunksz {
chunksz = remain
}
chunks[i] = chunk
}
// slice the chunks, advance each chunk slot as appropriate.
batch := make([]Interface, len(tr.chunks))
for i, chunk := range chunks {
var slice Interface
offset := tr.offsets[i]
switch int64(chunk.Len()) - offset {
case chunksz:
tr.slots[i]++
tr.offsets[i] = 0
if offset > 0 {
// need to slice
slice = NewSlice(chunk, offset, offset+chunksz)
} else {
// no need to slice
slice = chunk
slice.Retain()
}
default:
tr.offsets[i] += chunksz
slice = NewSlice(chunk, offset, offset+chunksz)
}
batch[i] = slice
}
tr.cur += chunksz
tr.rec = NewRecord(tr.tbl.Schema(), batch, chunksz)
for _, arr := range batch {
arr.Release()
}
return true
}
// Retain increases the reference count by 1.
// Retain may be called simultaneously from multiple goroutines.
func (tr *TableReader) Retain() {
atomic.AddInt64(&tr.refCount, 1)
}
// Release decreases the reference count by 1.
// When the reference count goes to zero, the memory is freed.
// Release may be called simultaneously from multiple goroutines.
func (tr *TableReader) Release() {
debug.Assert(atomic.LoadInt64(&tr.refCount) > 0, "too many releases")
if atomic.AddInt64(&tr.refCount, -1) == 0 {
tr.tbl.Release()
for _, chk := range tr.chunks {
chk.Release()
}
if tr.rec != nil {
tr.rec.Release()
}
tr.tbl = nil
tr.chunks = nil
tr.slots = nil
tr.offsets = nil
}
}
func imin64(a, b int64) int64 {
if a < b {
return a
}
return b
}
var (
_ Table = (*simpleTable)(nil)
_ RecordReader = (*TableReader)(nil)
)

View File

@@ -1,24 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package array
func min(a, b int) int {
if a < b {
return a
}
return b
}

View File

@@ -1,91 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package arrio exposes functions to manipulate records, exposing and using
// interfaces not unlike the ones defined in the stdlib io package.
package arrio // import "github.com/apache/arrow/go/arrow/arrio"
import (
"io"
"github.com/apache/arrow/go/arrow/array"
)
// Reader is the interface that wraps the Read method.
type Reader interface {
// Read reads the current record from the underlying stream and an error, if any.
// When the Reader reaches the end of the underlying stream, it returns (nil, io.EOF).
Read() (array.Record, error)
}
// ReaderAt is the interface that wraps the ReadAt method.
type ReaderAt interface {
// ReadAt reads the i-th record from the underlying stream and an error, if any.
ReadAt(i int64) (array.Record, error)
}
// Writer is the interface that wraps the Write method.
type Writer interface {
Write(rec array.Record) error
}
// Copy copies all the records available from src to dst.
// Copy returns the number of records copied and the first error
// encountered while copying, if any.
//
// A successful Copy returns err == nil, not err == EOF. Because Copy is
// defined to read from src until EOF, it does not treat an EOF from Read as an
// error to be reported.
func Copy(dst Writer, src Reader) (n int64, err error) {
for {
rec, err := src.Read()
if err != nil {
if err == io.EOF {
return n, nil
}
return n, err
}
err = dst.Write(rec)
if err != nil {
return n, err
}
n++
}
}
// CopyN copies n records (or until an error) from src to dst. It returns the
// number of records copied and the earliest error encountered while copying. On
// return, written == n if and only if err == nil.
func CopyN(dst Writer, src Reader, n int64) (written int64, err error) {
for ; written < n; written++ {
rec, err := src.Read()
if err != nil {
if err == io.EOF && written == n {
return written, nil
}
return written, err
}
err = dst.Write(rec)
if err != nil {
return written, err
}
}
if written != n && err == nil {
err = io.EOF
}
return written, err
}

View File

@@ -1,79 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package arrow
import (
"reflect"
)
type typeEqualsConfig struct {
metadata bool
}
// TypeEqualsOption is a functional option type used for configuring type
// equality checks.
type TypeEqualsOption func(*typeEqualsConfig)
// CheckMetadata is an option for TypeEquals that allows checking for metadata
// equality besides type equality. It only makes sense for STRUCT type.
func CheckMetadata() TypeEqualsOption {
return func(cfg *typeEqualsConfig) {
cfg.metadata = true
}
}
// TypeEquals checks if two DataType are the same, optionally checking metadata
// equality for STRUCT types.
func TypeEquals(left, right DataType, opts ...TypeEqualsOption) bool {
var cfg typeEqualsConfig
for _, opt := range opts {
opt(&cfg)
}
switch {
case left == nil || right == nil:
return false
case left.ID() != right.ID():
return false
}
// StructType is the only type that has metadata.
l, ok := left.(*StructType)
if !ok || cfg.metadata {
return reflect.DeepEqual(left, right)
}
r := right.(*StructType)
switch {
case len(l.fields) != len(r.fields):
return false
case !reflect.DeepEqual(l.index, r.index):
return false
}
for i := range l.fields {
leftField, rightField := l.fields[i], r.fields[i]
switch {
case leftField.Name != rightField.Name:
return false
case leftField.Nullable != rightField.Nullable:
return false
case !TypeEquals(leftField.Type, rightField.Type, opts...):
return false
}
}
return true
}

View File

@@ -1,143 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package arrow
// Type is a logical type. They can be expressed as
// either a primitive physical type (bytes or bits of some fixed size), a
// nested type consisting of other data types, or another data type (e.g. a
// timestamp encoded as an int64)
type Type int
const (
// NULL type having no physical storage
NULL Type = iota
// BOOL is a 1 bit, LSB bit-packed ordering
BOOL
// UINT8 is an Unsigned 8-bit little-endian integer
UINT8
// INT8 is a Signed 8-bit little-endian integer
INT8
// UINT16 is an Unsigned 16-bit little-endian integer
UINT16
// INT16 is a Signed 16-bit little-endian integer
INT16
// UINT32 is an Unsigned 32-bit little-endian integer
UINT32
// INT32 is a Signed 32-bit little-endian integer
INT32
// UINT64 is an Unsigned 64-bit little-endian integer
UINT64
// INT64 is a Signed 64-bit little-endian integer
INT64
// FLOAT16 is a 2-byte floating point value
FLOAT16
// FLOAT32 is a 4-byte floating point value
FLOAT32
// FLOAT64 is an 8-byte floating point value
FLOAT64
// STRING is a UTF8 variable-length string
STRING
// BINARY is a Variable-length byte type (no guarantee of UTF8-ness)
BINARY
// FIXED_SIZE_BINARY is a binary where each value occupies the same number of bytes
FIXED_SIZE_BINARY
// DATE32 is int32 days since the UNIX epoch
DATE32
// DATE64 is int64 milliseconds since the UNIX epoch
DATE64
// TIMESTAMP is an exact timestamp encoded with int64 since UNIX epoch
// Default unit millisecond
TIMESTAMP
// TIME32 is a signed 32-bit integer, representing either seconds or
// milliseconds since midnight
TIME32
// TIME64 is a signed 64-bit integer, representing either microseconds or
// nanoseconds since midnight
TIME64
// INTERVAL is YEAR_MONTH or DAY_TIME interval in SQL style
INTERVAL
// DECIMAL is a precision- and scale-based decimal type. Storage type depends on the
// parameters.
DECIMAL
// LIST is a list of some logical data type
LIST
// STRUCT of logical types
STRUCT
// UNION of logical types
UNION
// DICTIONARY aka Category type
DICTIONARY
// MAP is a repeated struct logical type
MAP
// Custom data type, implemented by user
EXTENSION
// Fixed size list of some logical type
FIXED_SIZE_LIST
// Measure of elapsed time in either seconds, milliseconds, microseconds
// or nanoseconds.
DURATION
)
// DataType is the representation of an Arrow type.
type DataType interface {
ID() Type
// Name is name of the data type.
Name() string
}
// FixedWidthDataType is the representation of an Arrow type that
// requires a fixed number of bits in memory for each element.
type FixedWidthDataType interface {
DataType
// BitWidth returns the number of bits required to store a single element of this data type in memory.
BitWidth() int
}
type BinaryDataType interface {
DataType
binary()
}

View File

@@ -1,41 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package arrow
type BinaryType struct{}
func (t *BinaryType) ID() Type { return BINARY }
func (t *BinaryType) Name() string { return "binary" }
func (t *BinaryType) String() string { return "binary" }
func (t *BinaryType) binary() {}
type StringType struct{}
func (t *StringType) ID() Type { return STRING }
func (t *StringType) Name() string { return "utf8" }
func (t *StringType) String() string { return "utf8" }
func (t *StringType) binary() {}
var (
BinaryTypes = struct {
Binary BinaryDataType
String BinaryDataType
}{
Binary: &BinaryType{},
String: &StringType{},
}
)

View File

@@ -1,213 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package arrow
import (
"fmt"
"strconv"
)
type BooleanType struct{}
func (t *BooleanType) ID() Type { return BOOL }
func (t *BooleanType) Name() string { return "bool" }
func (t *BooleanType) String() string { return "bool" }
// BitWidth returns the number of bits required to store a single element of this data type in memory.
func (t *BooleanType) BitWidth() int { return 1 }
type FixedSizeBinaryType struct {
ByteWidth int
}
func (*FixedSizeBinaryType) ID() Type { return FIXED_SIZE_BINARY }
func (*FixedSizeBinaryType) Name() string { return "fixed_size_binary" }
func (t *FixedSizeBinaryType) BitWidth() int { return 8 * t.ByteWidth }
func (t *FixedSizeBinaryType) String() string {
return "fixed_size_binary[" + strconv.Itoa(t.ByteWidth) + "]"
}
type (
Timestamp int64
Time32 int32
Time64 int64
TimeUnit int
Date32 int32
Date64 int64
Duration int64
)
const (
Nanosecond TimeUnit = iota
Microsecond
Millisecond
Second
)
func (u TimeUnit) String() string { return [...]string{"ns", "us", "ms", "s"}[uint(u)&3] }
// TimestampType is encoded as a 64-bit signed integer since the UNIX epoch (2017-01-01T00:00:00Z).
// The zero-value is a nanosecond and time zone neutral. Time zone neutral can be
// considered UTC without having "UTC" as a time zone.
type TimestampType struct {
Unit TimeUnit
TimeZone string
}
func (*TimestampType) ID() Type { return TIMESTAMP }
func (*TimestampType) Name() string { return "timestamp" }
func (t *TimestampType) String() string {
switch len(t.TimeZone) {
case 0:
return "timestamp[" + t.Unit.String() + "]"
default:
return "timestamp[" + t.Unit.String() + ", tz=" + t.TimeZone + "]"
}
}
// BitWidth returns the number of bits required to store a single element of this data type in memory.
func (*TimestampType) BitWidth() int { return 64 }
// Time32Type is encoded as a 32-bit signed integer, representing either seconds or milliseconds since midnight.
type Time32Type struct {
Unit TimeUnit
}
func (*Time32Type) ID() Type { return TIME32 }
func (*Time32Type) Name() string { return "time32" }
func (*Time32Type) BitWidth() int { return 32 }
func (t *Time32Type) String() string { return "time32[" + t.Unit.String() + "]" }
// Time64Type is encoded as a 64-bit signed integer, representing either microseconds or nanoseconds since midnight.
type Time64Type struct {
Unit TimeUnit
}
func (*Time64Type) ID() Type { return TIME64 }
func (*Time64Type) Name() string { return "time64" }
func (*Time64Type) BitWidth() int { return 64 }
func (t *Time64Type) String() string { return "time64[" + t.Unit.String() + "]" }
// DurationType is encoded as a 64-bit signed integer, representing an amount
// of elapsed time without any relation to a calendar artifact.
type DurationType struct {
Unit TimeUnit
}
func (*DurationType) ID() Type { return DURATION }
func (*DurationType) Name() string { return "duration" }
func (*DurationType) BitWidth() int { return 64 }
func (t *DurationType) String() string { return "duration[" + t.Unit.String() + "]" }
// Float16Type represents a floating point value encoded with a 16-bit precision.
type Float16Type struct{}
func (t *Float16Type) ID() Type { return FLOAT16 }
func (t *Float16Type) Name() string { return "float16" }
func (t *Float16Type) String() string { return "float16" }
// BitWidth returns the number of bits required to store a single element of this data type in memory.
func (t *Float16Type) BitWidth() int { return 16 }
// Decimal128Type represents a fixed-size 128-bit decimal type.
type Decimal128Type struct {
Precision int32
Scale int32
}
func (*Decimal128Type) ID() Type { return DECIMAL }
func (*Decimal128Type) Name() string { return "decimal" }
func (*Decimal128Type) BitWidth() int { return 16 }
func (t *Decimal128Type) String() string {
return fmt.Sprintf("%s(%d, %d)", t.Name(), t.Precision, t.Scale)
}
// MonthInterval represents a number of months.
type MonthInterval int32
// MonthIntervalType is encoded as a 32-bit signed integer,
// representing a number of months.
type MonthIntervalType struct{}
func (*MonthIntervalType) ID() Type { return INTERVAL }
func (*MonthIntervalType) Name() string { return "month_interval" }
func (*MonthIntervalType) String() string { return "month_interval" }
// BitWidth returns the number of bits required to store a single element of this data type in memory.
func (t *MonthIntervalType) BitWidth() int { return 32 }
// DayTimeInterval represents a number of days and milliseconds (fraction of day).
type DayTimeInterval struct {
Days int32 `json:"days"`
Milliseconds int32 `json:"milliseconds"`
}
// DayTimeIntervalType is encoded as a pair of 32-bit signed integer,
// representing a number of days and milliseconds (fraction of day).
type DayTimeIntervalType struct{}
func (*DayTimeIntervalType) ID() Type { return INTERVAL }
func (*DayTimeIntervalType) Name() string { return "day_time_interval" }
func (*DayTimeIntervalType) String() string { return "day_time_interval" }
// BitWidth returns the number of bits required to store a single element of this data type in memory.
func (t *DayTimeIntervalType) BitWidth() int { return 64 }
var (
FixedWidthTypes = struct {
Boolean FixedWidthDataType
Date32 FixedWidthDataType
Date64 FixedWidthDataType
DayTimeInterval FixedWidthDataType
Duration_s FixedWidthDataType
Duration_ms FixedWidthDataType
Duration_us FixedWidthDataType
Duration_ns FixedWidthDataType
Float16 FixedWidthDataType
MonthInterval FixedWidthDataType
Time32s FixedWidthDataType
Time32ms FixedWidthDataType
Time64us FixedWidthDataType
Time64ns FixedWidthDataType
Timestamp_s FixedWidthDataType
Timestamp_ms FixedWidthDataType
Timestamp_us FixedWidthDataType
Timestamp_ns FixedWidthDataType
}{
Boolean: &BooleanType{},
Date32: &Date32Type{},
Date64: &Date64Type{},
DayTimeInterval: &DayTimeIntervalType{},
Duration_s: &DurationType{Unit: Second},
Duration_ms: &DurationType{Unit: Millisecond},
Duration_us: &DurationType{Unit: Microsecond},
Duration_ns: &DurationType{Unit: Nanosecond},
Float16: &Float16Type{},
MonthInterval: &MonthIntervalType{},
Time32s: &Time32Type{Unit: Second},
Time32ms: &Time32Type{Unit: Millisecond},
Time64us: &Time64Type{Unit: Microsecond},
Time64ns: &Time64Type{Unit: Nanosecond},
Timestamp_s: &TimestampType{Unit: Second, TimeZone: "UTC"},
Timestamp_ms: &TimestampType{Unit: Millisecond, TimeZone: "UTC"},
Timestamp_us: &TimestampType{Unit: Microsecond, TimeZone: "UTC"},
Timestamp_ns: &TimestampType{Unit: Nanosecond, TimeZone: "UTC"},
}
_ FixedWidthDataType = (*FixedSizeBinaryType)(nil)
)

View File

@@ -1,180 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package arrow
import (
"fmt"
"reflect"
"strings"
)
// ListType describes a nested type in which each array slot contains
// a variable-size sequence of values, all having the same relative type.
type ListType struct {
elem DataType // DataType of the list's elements
}
// ListOf returns the list type with element type t.
// For example, if t represents int32, ListOf(t) represents []int32.
//
// ListOf panics if t is nil or invalid.
func ListOf(t DataType) *ListType {
if t == nil {
panic("arrow: nil DataType")
}
return &ListType{elem: t}
}
func (*ListType) ID() Type { return LIST }
func (*ListType) Name() string { return "list" }
func (t *ListType) String() string { return fmt.Sprintf("list<item: %v>", t.elem) }
// Elem returns the ListType's element type.
func (t *ListType) Elem() DataType { return t.elem }
// FixedSizeListType describes a nested type in which each array slot contains
// a fixed-size sequence of values, all having the same relative type.
type FixedSizeListType struct {
n int32 // number of elements in the list
elem DataType // DataType of the list's elements
}
// FixedSizeListOf returns the list type with element type t.
// For example, if t represents int32, FixedSizeListOf(10, t) represents [10]int32.
//
// FixedSizeListOf panics if t is nil or invalid.
// FixedSizeListOf panics if n is <= 0.
func FixedSizeListOf(n int32, t DataType) *FixedSizeListType {
if t == nil {
panic("arrow: nil DataType")
}
if n <= 0 {
panic("arrow: invalid size")
}
return &FixedSizeListType{elem: t, n: n}
}
func (*FixedSizeListType) ID() Type { return FIXED_SIZE_LIST }
func (*FixedSizeListType) Name() string { return "fixed_size_list" }
func (t *FixedSizeListType) String() string {
return fmt.Sprintf("fixed_size_list<item: %v>[%d]", t.elem, t.n)
}
// Elem returns the FixedSizeListType's element type.
func (t *FixedSizeListType) Elem() DataType { return t.elem }
// Len returns the FixedSizeListType's size.
func (t *FixedSizeListType) Len() int32 { return t.n }
// StructType describes a nested type parameterized by an ordered sequence
// of relative types, called its fields.
type StructType struct {
fields []Field
index map[string]int
meta Metadata
}
// StructOf returns the struct type with fields fs.
//
// StructOf panics if there are duplicated fields.
// StructOf panics if there is a field with an invalid DataType.
func StructOf(fs ...Field) *StructType {
n := len(fs)
if n == 0 {
return &StructType{}
}
t := &StructType{
fields: make([]Field, n),
index: make(map[string]int, n),
}
for i, f := range fs {
if f.Type == nil {
panic("arrow: field with nil DataType")
}
t.fields[i] = Field{
Name: f.Name,
Type: f.Type,
Nullable: f.Nullable,
Metadata: f.Metadata.clone(),
}
if _, dup := t.index[f.Name]; dup {
panic(fmt.Errorf("arrow: duplicate field with name %q", f.Name))
}
t.index[f.Name] = i
}
return t
}
func (*StructType) ID() Type { return STRUCT }
func (*StructType) Name() string { return "struct" }
func (t *StructType) String() string {
o := new(strings.Builder)
o.WriteString("struct<")
for i, f := range t.fields {
if i > 0 {
o.WriteString(", ")
}
o.WriteString(fmt.Sprintf("%s: %v", f.Name, f.Type))
}
o.WriteString(">")
return o.String()
}
func (t *StructType) Fields() []Field { return t.fields }
func (t *StructType) Field(i int) Field { return t.fields[i] }
func (t *StructType) FieldByName(name string) (Field, bool) {
i, ok := t.index[name]
if !ok {
return Field{}, false
}
return t.fields[i], true
}
type Field struct {
Name string // Field name
Type DataType // The field's data type
Nullable bool // Fields can be nullable
Metadata Metadata // The field's metadata, if any
}
func (f Field) HasMetadata() bool { return f.Metadata.Len() != 0 }
func (f Field) Equal(o Field) bool {
return reflect.DeepEqual(f, o)
}
func (f Field) String() string {
o := new(strings.Builder)
nullable := ""
if f.Nullable {
nullable = ", nullable"
}
fmt.Fprintf(o, "%s: type=%v%v", f.Name, f.Type, nullable)
if f.HasMetadata() {
fmt.Fprintf(o, "\n%*.smetadata: %v", len(f.Name)+2, "", f.Metadata)
}
return o.String()
}
var (
_ DataType = (*ListType)(nil)
_ DataType = (*StructType)(nil)
)

View File

@@ -1,29 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package arrow
// NullType describes a degenerate array, with zero physical storage.
type NullType struct{}
func (*NullType) ID() Type { return NULL }
func (*NullType) Name() string { return "null" }
func (*NullType) String() string { return "null" }
var (
Null *NullType
_ DataType = Null
)

View File

@@ -1,134 +0,0 @@
// Code generated by datatype_numeric.gen.go.tmpl. DO NOT EDIT.
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package arrow
type Int8Type struct{}
func (t *Int8Type) ID() Type { return INT8 }
func (t *Int8Type) Name() string { return "int8" }
func (t *Int8Type) String() string { return "int8" }
func (t *Int8Type) BitWidth() int { return 8 }
type Int16Type struct{}
func (t *Int16Type) ID() Type { return INT16 }
func (t *Int16Type) Name() string { return "int16" }
func (t *Int16Type) String() string { return "int16" }
func (t *Int16Type) BitWidth() int { return 16 }
type Int32Type struct{}
func (t *Int32Type) ID() Type { return INT32 }
func (t *Int32Type) Name() string { return "int32" }
func (t *Int32Type) String() string { return "int32" }
func (t *Int32Type) BitWidth() int { return 32 }
type Int64Type struct{}
func (t *Int64Type) ID() Type { return INT64 }
func (t *Int64Type) Name() string { return "int64" }
func (t *Int64Type) String() string { return "int64" }
func (t *Int64Type) BitWidth() int { return 64 }
type Uint8Type struct{}
func (t *Uint8Type) ID() Type { return UINT8 }
func (t *Uint8Type) Name() string { return "uint8" }
func (t *Uint8Type) String() string { return "uint8" }
func (t *Uint8Type) BitWidth() int { return 8 }
type Uint16Type struct{}
func (t *Uint16Type) ID() Type { return UINT16 }
func (t *Uint16Type) Name() string { return "uint16" }
func (t *Uint16Type) String() string { return "uint16" }
func (t *Uint16Type) BitWidth() int { return 16 }
type Uint32Type struct{}
func (t *Uint32Type) ID() Type { return UINT32 }
func (t *Uint32Type) Name() string { return "uint32" }
func (t *Uint32Type) String() string { return "uint32" }
func (t *Uint32Type) BitWidth() int { return 32 }
type Uint64Type struct{}
func (t *Uint64Type) ID() Type { return UINT64 }
func (t *Uint64Type) Name() string { return "uint64" }
func (t *Uint64Type) String() string { return "uint64" }
func (t *Uint64Type) BitWidth() int { return 64 }
type Float32Type struct{}
func (t *Float32Type) ID() Type { return FLOAT32 }
func (t *Float32Type) Name() string { return "float32" }
func (t *Float32Type) String() string { return "float32" }
func (t *Float32Type) BitWidth() int { return 32 }
type Float64Type struct{}
func (t *Float64Type) ID() Type { return FLOAT64 }
func (t *Float64Type) Name() string { return "float64" }
func (t *Float64Type) String() string { return "float64" }
func (t *Float64Type) BitWidth() int { return 64 }
type Date32Type struct{}
func (t *Date32Type) ID() Type { return DATE32 }
func (t *Date32Type) Name() string { return "date32" }
func (t *Date32Type) String() string { return "date32" }
func (t *Date32Type) BitWidth() int { return 32 }
type Date64Type struct{}
func (t *Date64Type) ID() Type { return DATE64 }
func (t *Date64Type) Name() string { return "date64" }
func (t *Date64Type) String() string { return "date64" }
func (t *Date64Type) BitWidth() int { return 64 }
var (
PrimitiveTypes = struct {
Int8 DataType
Int16 DataType
Int32 DataType
Int64 DataType
Uint8 DataType
Uint16 DataType
Uint32 DataType
Uint64 DataType
Float32 DataType
Float64 DataType
Date32 DataType
Date64 DataType
}{
Int8: &Int8Type{},
Int16: &Int16Type{},
Int32: &Int32Type{},
Int64: &Int64Type{},
Uint8: &Uint8Type{},
Uint16: &Uint16Type{},
Uint32: &Uint32Type{},
Uint64: &Uint64Type{},
Float32: &Float32Type{},
Float64: &Float64Type{},
Date32: &Date32Type{},
Date64: &Date64Type{},
}
)

View File

@@ -1,40 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package arrow
{{range .In}}
type {{.Name}}Type struct {}
func (t *{{.Name}}Type) ID() Type { return {{.Name|upper}} }
func (t *{{.Name}}Type) Name() string { return "{{.Name|lower}}" }
func (t *{{.Name}}Type) String() string { return "{{.Name|lower}}" }
func (t *{{.Name}}Type) BitWidth() int { return {{.Size}} }
{{end}}
var (
PrimitiveTypes = struct {
{{range .In}}
{{.Name}} DataType
{{- end}}
}{
{{range .In}}
{{.Name}}: &{{.Name}}Type{},
{{- end}}
}
)

View File

@@ -1,62 +0,0 @@
[
{
"Name": "Int8",
"Type": "int8",
"Size": 8
},
{
"Name": "Int16",
"Type": "int16",
"Size": 16
},
{
"Name": "Int32",
"Type": "int32",
"Size": 32
},
{
"Name": "Int64",
"Type": "int64",
"Size": 64
},
{
"Name": "Uint8",
"Type": "uint8",
"Size": 8
},
{
"Name": "Uint16",
"Type": "uint16",
"Size": 16
},
{
"Name": "Uint32",
"Type": "uint32",
"Size": 32
},
{
"Name": "Uint64",
"Type": "uint64",
"Size": 64
},
{
"Name": "Float32",
"Type": "float32",
"Size": 32
},
{
"Name": "Float64",
"Type": "float64",
"Size": 64
},
{
"Name": "Date32",
"Type": "date32",
"Size": 32
},
{
"Name": "Date64",
"Type": "date64",
"Size": 64
}
]

View File

@@ -1,73 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package decimal128 // import "github.com/apache/arrow/go/arrow/decimal128"
var (
MaxDecimal128 = New(542101086242752217, 687399551400673280-1)
)
// Num represents a signed 128-bit integer in two's complement.
// Calculations wrap around and overflow is ignored.
//
// For a discussion of the algorithms, look at Knuth's volume 2,
// Semi-numerical Algorithms section 4.3.1.
//
// Adapted from the Apache ORC C++ implementation
type Num struct {
lo uint64 // low bits
hi int64 // high bits
}
// New returns a new signed 128-bit integer value.
func New(hi int64, lo uint64) Num {
return Num{lo: lo, hi: hi}
}
// FromU64 returns a new signed 128-bit integer value from the provided uint64 one.
func FromU64(v uint64) Num {
return New(0, v)
}
// FromI64 returns a new signed 128-bit integer value from the provided int64 one.
func FromI64(v int64) Num {
switch {
case v > 0:
return New(0, uint64(v))
case v < 0:
return New(-1, uint64(v))
default:
return Num{}
}
}
// LowBits returns the low bits of the two's complement representation of the number.
func (n Num) LowBits() uint64 { return n.lo }
// HighBits returns the high bits of the two's complement representation of the number.
func (n Num) HighBits() int64 { return n.hi }
// Sign returns:
//
// -1 if x < 0
// 0 if x == 0
// +1 if x > 0
func (n Num) Sign() int {
if n == (Num{}) {
return 0
}
return int(1 | (n.hi >> 63))
}

View File

@@ -1,39 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Package arrow provides an implementation of Apache Arrow.
Apache Arrow is a cross-language development platform for in-memory data. It specifies a standardized
language-independent columnar memory format for flat and hierarchical data, organized for efficient analytic
operations on modern hardware. It also provides computational libraries and zero-copy streaming
messaging and inter-process communication.
Basics
The fundamental data structure in Arrow is an Array, which holds a sequence of values of the same type. An array
consists of memory holding the data and an additional validity bitmap that indicates if the corresponding entry in the
array is valid (not null). If the array has no null entries, it is possible to omit this bitmap.
*/
package arrow
//go:generate go run _tools/tmpl/main.go -i -data=numeric.tmpldata type_traits_numeric.gen.go.tmpl type_traits_numeric.gen_test.go.tmpl array/numeric.gen.go.tmpl array/numericbuilder.gen.go.tmpl array/bufferbuilder_numeric.gen.go.tmpl
//go:generate go run _tools/tmpl/main.go -i -data=datatype_numeric.gen.go.tmpldata datatype_numeric.gen.go.tmpl tensor/numeric.gen.go.tmpl tensor/numeric.gen_test.go.tmpl
//go:generate go run ./gen-flatbuffers.go
// stringer
//go:generate stringer -type=Type

View File

@@ -1,70 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package float16 // import "github.com/apache/arrow/go/arrow/float16"
import (
"math"
"strconv"
)
// Num represents a half-precision floating point value (float16)
// stored on 16 bits.
//
// See https://en.wikipedia.org/wiki/Half-precision_floating-point_format for more informations.
type Num struct {
bits uint16
}
// New creates a new half-precision floating point value from the provided
// float32 value.
func New(f float32) Num {
b := math.Float32bits(f)
sn := uint16((b >> 31) & 0x1)
exp := (b >> 23) & 0xff
res := int16(exp) - 127 + 15
fc := uint16(b>>13) & 0x3ff
switch {
case exp == 0:
res = 0
case exp == 0xff:
res = 0x1f
case res > 0x1e:
res = 0x1f
fc = 0
case res < 0x01:
res = 0
fc = 0
}
return Num{bits: (sn << 15) | uint16(res<<10) | fc}
}
func (f Num) Float32() float32 {
sn := uint32((f.bits >> 15) & 0x1)
exp := (f.bits >> 10) & 0x1f
res := uint32(exp) + 127 - 15
fc := uint32(f.bits & 0x3ff)
switch {
case exp == 0:
res = 0
case exp == 0x1f:
res = 0xff
}
return math.Float32frombits((sn << 31) | (res << 23) | (fc << 13))
}
func (f Num) Uint16() uint16 { return f.bits }
func (f Num) String() string { return strconv.FormatFloat(float64(f.Float32()), 'g', -1, 32) }

View File

@@ -1,27 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
module github.com/apache/arrow/go/arrow
go 1.12
require (
github.com/davecgh/go-spew v1.1.0 // indirect
github.com/google/flatbuffers v1.11.0
github.com/pkg/errors v0.8.1
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.0
)

View File

@@ -1,10 +0,0 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/flatbuffers v1.11.0 h1:O7CEyB8Cb3/DmtxODGtLHcEvpr81Jm5qLg/hsHnxA2A=
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.0 h1:LThGCOvhuJic9Gyd1VBCkhyUXmO8vKaBFvBsJ2k03rg=
github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=

View File

@@ -1,156 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package bitutil
import (
"math/bits"
"reflect"
"unsafe"
)
var (
BitMask = [8]byte{1, 2, 4, 8, 16, 32, 64, 128}
FlippedBitMask = [8]byte{254, 253, 251, 247, 239, 223, 191, 127}
)
// IsMultipleOf8 returns whether v is a multiple of 8.
func IsMultipleOf8(v int64) bool { return v&7 == 0 }
func BytesForBits(bits int64) int64 { return (bits + 7) >> 3 }
// NextPowerOf2 rounds x to the next power of two.
func NextPowerOf2(x int) int { return 1 << uint(bits.Len(uint(x))) }
// CeilByte rounds size to the next multiple of 8.
func CeilByte(size int) int { return (size + 7) &^ 7 }
// CeilByte64 rounds size to the next multiple of 8.
func CeilByte64(size int64) int64 { return (size + 7) &^ 7 }
// BitIsSet returns true if the bit at index i in buf is set (1).
func BitIsSet(buf []byte, i int) bool { return (buf[uint(i)/8] & BitMask[byte(i)%8]) != 0 }
// BitIsNotSet returns true if the bit at index i in buf is not set (0).
func BitIsNotSet(buf []byte, i int) bool { return (buf[uint(i)/8] & BitMask[byte(i)%8]) == 0 }
// SetBit sets the bit at index i in buf to 1.
func SetBit(buf []byte, i int) { buf[uint(i)/8] |= BitMask[byte(i)%8] }
// ClearBit sets the bit at index i in buf to 0.
func ClearBit(buf []byte, i int) { buf[uint(i)/8] &= FlippedBitMask[byte(i)%8] }
// SetBitTo sets the bit at index i in buf to val.
func SetBitTo(buf []byte, i int, val bool) {
if val {
SetBit(buf, i)
} else {
ClearBit(buf, i)
}
}
// CountSetBits counts the number of 1's in buf up to n bits.
func CountSetBits(buf []byte, offset, n int) int {
if offset > 0 {
return countSetBitsWithOffset(buf, offset, n)
}
count := 0
uint64Bytes := n / uint64SizeBits * 8
for _, v := range bytesToUint64(buf[:uint64Bytes]) {
count += bits.OnesCount64(v)
}
for _, v := range buf[uint64Bytes : n/8] {
count += bits.OnesCount8(v)
}
// tail bits
for i := n &^ 0x7; i < n; i++ {
if BitIsSet(buf, i) {
count++
}
}
return count
}
func countSetBitsWithOffset(buf []byte, offset, n int) int {
count := 0
beg := offset
end := offset + n
begU8 := roundUp(beg, uint64SizeBits)
init := min(n, begU8-beg)
for i := offset; i < beg+init; i++ {
if BitIsSet(buf, i) {
count++
}
}
nU64 := (n - init) / uint64SizeBits
begU64 := begU8 / uint64SizeBits
endU64 := begU64 + nU64
bufU64 := bytesToUint64(buf)
if begU64 < len(bufU64) {
for _, v := range bufU64[begU64:endU64] {
count += bits.OnesCount64(v)
}
}
// FIXME: use a fallback to bits.OnesCount8
// before counting the tail bits.
tail := beg + init + nU64*uint64SizeBits
for i := tail; i < end; i++ {
if BitIsSet(buf, i) {
count++
}
}
return count
}
func roundUp(v, f int) int {
return (v + (f - 1)) / f * f
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
const (
uint64SizeBytes = int(unsafe.Sizeof(uint64(0)))
uint64SizeBits = uint64SizeBytes * 8
)
func bytesToUint64(b []byte) []uint64 {
h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
var res []uint64
s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
s.Data = h.Data
s.Len = h.Len / uint64SizeBytes
s.Cap = h.Cap / uint64SizeBytes
return res
}

View File

@@ -1,42 +0,0 @@
<!---
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
# Package cpu
Copied from Go src/internal/cpu
## Extras
### Intel
The `INTEL_DISABLE_EXT` environment variable can control which CPU extensions are available for
the running process. It should be a comma-separate list of upper-case strings as follows
| Flag | Description |
| -------- | ----------- |
| `ALL` | Disable all CPU extensions and fall back to Go implementation |
| `AVX2` | Disable AVX2 optimizations |
| `AVX` | Disable AVX optimizations |
| `SSE` | Disable all SSE optimizations |
| `SSE4` | Disable SSE42, SSE41 optimizations |
| `SSSE3` | Disable supplemental SSE3 optimizations |
| `SSE3` | Disable SSE3 optimizations |
| `SSE2` | Disable SSE2 optimizations |
Any unrecognized flags will be ignored and therefore it is possible to leave the environment variable with a bogus value such as `NONE` when experimenting.

View File

@@ -1,77 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package cpu implements processor feature detection
// used by the Go standard library.
package cpu
var X86 x86
// The booleans in x86 contain the correspondingly named cpuid feature bit.
// HasAVX and HasAVX2 are only set if the OS does support XMM and YMM registers
// in addition to the cpuid feature bit being set.
// The struct is padded to avoid false sharing.
type x86 struct {
_ [CacheLineSize]byte
HasAES bool
HasADX bool
HasAVX bool
HasAVX2 bool
HasBMI1 bool
HasBMI2 bool
HasERMS bool
HasFMA bool
HasOSXSAVE bool
HasPCLMULQDQ bool
HasPOPCNT bool
HasSSE2 bool
HasSSE3 bool
HasSSSE3 bool
HasSSE41 bool
HasSSE42 bool
_ [CacheLineSize]byte
}
var PPC64 ppc64
// For ppc64x, it is safe to check only for ISA level starting on ISA v3.00,
// since there are no optional categories. There are some exceptions that also
// require kernel support to work (darn, scv), so there are capability bits for
// those as well. The minimum processor requirement is POWER8 (ISA 2.07), so we
// maintain some of the old capability checks for optional categories for
// safety.
// The struct is padded to avoid false sharing.
type ppc64 struct {
_ [CacheLineSize]byte
HasVMX bool // Vector unit (Altivec)
HasDFP bool // Decimal Floating Point unit
HasVSX bool // Vector-scalar unit
HasHTM bool // Hardware Transactional Memory
HasISEL bool // Integer select
HasVCRYPTO bool // Vector cryptography
HasHTMNOSC bool // HTM: kernel-aborted transaction in syscalls
HasDARN bool // Hardware random number generator (requires kernel enablement)
HasSCV bool // Syscall vectored (requires kernel enablement)
IsPOWER8 bool // ISA v2.07 (POWER8)
IsPOWER9 bool // ISA v3.00 (POWER9)
_ [CacheLineSize]byte
}
var ARM64 arm64
// The booleans in arm64 contain the correspondingly named cpu feature bit.
// The struct is padded to avoid false sharing.
type arm64 struct {
_ [CacheLineSize]byte
HasFP bool
HasASIMD bool
HasEVTSTRM bool
HasAES bool
HasPMULL bool
HasSHA1 bool
HasSHA2 bool
HasCRC32 bool
HasATOMICS bool
_ [CacheLineSize]byte
}

View File

@@ -1,107 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build 386 amd64 amd64p32
package cpu
import (
"os"
"strings"
)
const CacheLineSize = 64
// cpuid is implemented in cpu_x86.s.
func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
// xgetbv with ecx = 0 is implemented in cpu_x86.s.
func xgetbv() (eax, edx uint32)
func init() {
maxID, _, _, _ := cpuid(0, 0)
if maxID < 1 {
return
}
_, _, ecx1, edx1 := cpuid(1, 0)
X86.HasSSE2 = isSet(26, edx1)
X86.HasSSE3 = isSet(0, ecx1)
X86.HasPCLMULQDQ = isSet(1, ecx1)
X86.HasSSSE3 = isSet(9, ecx1)
X86.HasFMA = isSet(12, ecx1)
X86.HasSSE41 = isSet(19, ecx1)
X86.HasSSE42 = isSet(20, ecx1)
X86.HasPOPCNT = isSet(23, ecx1)
X86.HasAES = isSet(25, ecx1)
X86.HasOSXSAVE = isSet(27, ecx1)
osSupportsAVX := false
// For XGETBV, OSXSAVE bit is required and sufficient.
if X86.HasOSXSAVE {
eax, _ := xgetbv()
// Check if XMM and YMM registers have OS support.
osSupportsAVX = isSet(1, eax) && isSet(2, eax)
}
X86.HasAVX = isSet(28, ecx1) && osSupportsAVX
if maxID < 7 {
return
}
_, ebx7, _, _ := cpuid(7, 0)
X86.HasBMI1 = isSet(3, ebx7)
X86.HasAVX2 = isSet(5, ebx7) && osSupportsAVX
X86.HasBMI2 = isSet(8, ebx7)
X86.HasERMS = isSet(9, ebx7)
X86.HasADX = isSet(19, ebx7)
// NOTE(sgc): added ability to disable extension via environment
checkEnvironment()
}
func checkEnvironment() {
if ext, ok := os.LookupEnv("INTEL_DISABLE_EXT"); ok {
exts := strings.Split(ext, ",")
for _, x := range exts {
switch x {
case "ALL":
X86.HasAVX2 = false
X86.HasAVX = false
X86.HasSSE42 = false
X86.HasSSE41 = false
X86.HasSSSE3 = false
X86.HasSSE3 = false
X86.HasSSE2 = false
case "AVX2":
X86.HasAVX2 = false
case "AVX":
X86.HasAVX = false
case "SSE":
X86.HasSSE42 = false
X86.HasSSE41 = false
X86.HasSSSE3 = false
X86.HasSSE3 = false
X86.HasSSE2 = false
case "SSE4":
X86.HasSSE42 = false
X86.HasSSE41 = false
case "SSSE3":
X86.HasSSSE3 = false
case "SSE3":
X86.HasSSE3 = false
case "SSE2":
X86.HasSSE2 = false
}
}
}
}
func isSet(bitpos uint, value uint32) bool {
return value&(1<<bitpos) != 0
}

View File

@@ -1,32 +0,0 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build 386 amd64 amd64p32
#include "textflag.h"
// func cpuid(eaxArg, ecxArg uint32) (eax, ebx, ecx, edx uint32)
TEXT ·cpuid(SB), NOSPLIT, $0-24
MOVL eaxArg+0(FP), AX
MOVL ecxArg+4(FP), CX
CPUID
MOVL AX, eax+8(FP)
MOVL BX, ebx+12(FP)
MOVL CX, ecx+16(FP)
MOVL DX, edx+20(FP)
RET
// func xgetbv() (eax, edx uint32)
TEXT ·xgetbv(SB),NOSPLIT,$0-8
#ifdef GOOS_nacl
// nacl does not support XGETBV.
MOVL $0, eax+0(FP)
MOVL $0, edx+4(FP)
#else
MOVL $0, CX
XGETBV
MOVL AX, eax+0(FP)
MOVL DX, edx+4(FP)
#endif
RET

View File

@@ -1,24 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !assert
package debug
// Assert will panic with msg if cond is false.
//
// msg must be a string, func() string or fmt.Stringer.
func Assert(cond bool, msg interface{}) {}

View File

@@ -1,28 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build assert
package debug
// Assert will panic with msg if cond is false.
//
// msg must be a string, func() string or fmt.Stringer.
func Assert(cond bool, msg interface{}) {
if !cond {
panic(getStringValue(msg))
}
}

View File

@@ -1,32 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Package debug provides APIs for conditional runtime assertions and debug logging.
Using Assert
To enable runtime assertions, build with the assert tag. When the assert tag is omitted,
the code for the assertion will be omitted from the binary.
Using Log
To enable runtime debug logs, build with the debug tag. When the debug tag is omitted,
the code for logging will be omitted from the binary.
*/
package debug

View File

@@ -1,21 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build !debug
package debug
func Log(interface{}) {}

View File

@@ -1,32 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build debug
package debug
import (
"log"
"os"
)
var (
debug = log.New(os.Stderr, "[D] ", log.LstdFlags)
)
func Log(msg interface{}) {
debug.Output(1, getStringValue(msg))
}

View File

@@ -1,37 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// +build debug assert
package debug
import "fmt"
func getStringValue(v interface{}) string {
switch a := v.(type) {
case func() string:
return a()
case string:
return a
case fmt.Stringer:
return a.String()
default:
panic(fmt.Sprintf("unexpected type, %t", v))
}
}

View File

@@ -1,50 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
type Binary struct {
_tab flatbuffers.Table
}
func GetRootAsBinary(buf []byte, offset flatbuffers.UOffsetT) *Binary {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Binary{}
x.Init(buf, n+offset)
return x
}
func (rcv *Binary) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Binary) Table() flatbuffers.Table {
return rcv._tab
}
func BinaryStart(builder *flatbuffers.Builder) {
builder.StartObject(0)
}
func BinaryEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -1,74 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
type Block struct {
_tab flatbuffers.Struct
}
func (rcv *Block) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Block) Table() flatbuffers.Table {
return rcv._tab.Table
}
/// Index to the start of the RecordBlock (note this is past the Message header)
func (rcv *Block) Offset() int64 {
return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(0))
}
/// Index to the start of the RecordBlock (note this is past the Message header)
func (rcv *Block) MutateOffset(n int64) bool {
return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(0), n)
}
/// Length of the metadata
func (rcv *Block) MetaDataLength() int32 {
return rcv._tab.GetInt32(rcv._tab.Pos + flatbuffers.UOffsetT(8))
}
/// Length of the metadata
func (rcv *Block) MutateMetaDataLength(n int32) bool {
return rcv._tab.MutateInt32(rcv._tab.Pos+flatbuffers.UOffsetT(8), n)
}
/// Length of the data (this is aligned so there can be a gap between this and
/// the metatdata).
func (rcv *Block) BodyLength() int64 {
return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(16))
}
/// Length of the data (this is aligned so there can be a gap between this and
/// the metatdata).
func (rcv *Block) MutateBodyLength(n int64) bool {
return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(16), n)
}
func CreateBlock(builder *flatbuffers.Builder, offset int64, metaDataLength int32, bodyLength int64) flatbuffers.UOffsetT {
builder.Prep(8, 24)
builder.PrependInt64(bodyLength)
builder.Pad(4)
builder.PrependInt32(metaDataLength)
builder.PrependInt64(offset)
return builder.Offset()
}

View File

@@ -1,50 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
type Bool struct {
_tab flatbuffers.Table
}
func GetRootAsBool(buf []byte, offset flatbuffers.UOffsetT) *Bool {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Bool{}
x.Init(buf, n+offset)
return x
}
func (rcv *Bool) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Bool) Table() flatbuffers.Table {
return rcv._tab
}
func BoolStart(builder *flatbuffers.Builder) {
builder.StartObject(0)
}
func BoolEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -1,67 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
/// ----------------------------------------------------------------------
/// A Buffer represents a single contiguous memory segment
type Buffer struct {
_tab flatbuffers.Struct
}
func (rcv *Buffer) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Buffer) Table() flatbuffers.Table {
return rcv._tab.Table
}
/// The relative offset into the shared memory page where the bytes for this
/// buffer starts
func (rcv *Buffer) Offset() int64 {
return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(0))
}
/// The relative offset into the shared memory page where the bytes for this
/// buffer starts
func (rcv *Buffer) MutateOffset(n int64) bool {
return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(0), n)
}
/// The absolute length (in bytes) of the memory buffer. The memory is found
/// from offset (inclusive) to offset + length (non-inclusive).
func (rcv *Buffer) Length() int64 {
return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(8))
}
/// The absolute length (in bytes) of the memory buffer. The memory is found
/// from offset (inclusive) to offset + length (non-inclusive).
func (rcv *Buffer) MutateLength(n int64) bool {
return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(8), n)
}
func CreateBuffer(builder *flatbuffers.Builder, offset int64, length int64) flatbuffers.UOffsetT {
builder.Prep(8, 16)
builder.PrependInt64(length)
builder.PrependInt64(offset)
return builder.Offset()
}

View File

@@ -1,71 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
/// Date is either a 32-bit or 64-bit type representing elapsed time since UNIX
/// epoch (1970-01-01), stored in either of two units:
///
/// * Milliseconds (64 bits) indicating UNIX time elapsed since the epoch (no
/// leap seconds), where the values are evenly divisible by 86400000
/// * Days (32 bits) since the UNIX epoch
type Date struct {
_tab flatbuffers.Table
}
func GetRootAsDate(buf []byte, offset flatbuffers.UOffsetT) *Date {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Date{}
x.Init(buf, n+offset)
return x
}
func (rcv *Date) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Date) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *Date) Unit() DateUnit {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetInt16(o + rcv._tab.Pos)
}
return 1
}
func (rcv *Date) MutateUnit(n DateUnit) bool {
return rcv._tab.MutateInt16Slot(4, n)
}
func DateStart(builder *flatbuffers.Builder) {
builder.StartObject(1)
}
func DateAddUnit(builder *flatbuffers.Builder, unit int16) {
builder.PrependInt16Slot(0, unit, 1)
}
func DateEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -1,31 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
type DateUnit = int16
const (
DateUnitDAY DateUnit = 0
DateUnitMILLISECOND DateUnit = 1
)
var EnumNamesDateUnit = map[DateUnit]string{
DateUnitDAY:"DAY",
DateUnitMILLISECOND:"MILLISECOND",
}

View File

@@ -1,84 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
type Decimal struct {
_tab flatbuffers.Table
}
func GetRootAsDecimal(buf []byte, offset flatbuffers.UOffsetT) *Decimal {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Decimal{}
x.Init(buf, n+offset)
return x
}
func (rcv *Decimal) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Decimal) Table() flatbuffers.Table {
return rcv._tab
}
/// Total number of decimal digits
func (rcv *Decimal) Precision() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
/// Total number of decimal digits
func (rcv *Decimal) MutatePrecision(n int32) bool {
return rcv._tab.MutateInt32Slot(4, n)
}
/// Number of digits after the decimal point "."
func (rcv *Decimal) Scale() int32 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetInt32(o + rcv._tab.Pos)
}
return 0
}
/// Number of digits after the decimal point "."
func (rcv *Decimal) MutateScale(n int32) bool {
return rcv._tab.MutateInt32Slot(6, n)
}
func DecimalStart(builder *flatbuffers.Builder) {
builder.StartObject(2)
}
func DecimalAddPrecision(builder *flatbuffers.Builder, precision int32) {
builder.PrependInt32Slot(0, precision, 0)
}
func DecimalAddScale(builder *flatbuffers.Builder, scale int32) {
builder.PrependInt32Slot(1, scale, 0)
}
func DecimalEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -1,106 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
/// For sending dictionary encoding information. Any Field can be
/// dictionary-encoded, but in this case none of its children may be
/// dictionary-encoded.
/// There is one vector / column per dictionary, but that vector / column
/// may be spread across multiple dictionary batches by using the isDelta
/// flag
type DictionaryBatch struct {
_tab flatbuffers.Table
}
func GetRootAsDictionaryBatch(buf []byte, offset flatbuffers.UOffsetT) *DictionaryBatch {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &DictionaryBatch{}
x.Init(buf, n+offset)
return x
}
func (rcv *DictionaryBatch) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *DictionaryBatch) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *DictionaryBatch) Id() int64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetInt64(o + rcv._tab.Pos)
}
return 0
}
func (rcv *DictionaryBatch) MutateId(n int64) bool {
return rcv._tab.MutateInt64Slot(4, n)
}
func (rcv *DictionaryBatch) Data(obj *RecordBatch) *RecordBatch {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(RecordBatch)
}
obj.Init(rcv._tab.Bytes, x)
return obj
}
return nil
}
/// If isDelta is true the values in the dictionary are to be appended to a
/// dictionary with the indicated id
func (rcv *DictionaryBatch) IsDelta() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
/// If isDelta is true the values in the dictionary are to be appended to a
/// dictionary with the indicated id
func (rcv *DictionaryBatch) MutateIsDelta(n bool) bool {
return rcv._tab.MutateBoolSlot(8, n)
}
func DictionaryBatchStart(builder *flatbuffers.Builder) {
builder.StartObject(3)
}
func DictionaryBatchAddId(builder *flatbuffers.Builder, id int64) {
builder.PrependInt64Slot(0, id, 0)
}
func DictionaryBatchAddData(builder *flatbuffers.Builder, data flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(data), 0)
}
func DictionaryBatchAddIsDelta(builder *flatbuffers.Builder, isDelta bool) {
builder.PrependBoolSlot(2, isDelta, false)
}
func DictionaryBatchEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -1,116 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
/// ----------------------------------------------------------------------
/// Dictionary encoding metadata
type DictionaryEncoding struct {
_tab flatbuffers.Table
}
func GetRootAsDictionaryEncoding(buf []byte, offset flatbuffers.UOffsetT) *DictionaryEncoding {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &DictionaryEncoding{}
x.Init(buf, n+offset)
return x
}
func (rcv *DictionaryEncoding) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *DictionaryEncoding) Table() flatbuffers.Table {
return rcv._tab
}
/// The known dictionary id in the application where this data is used. In
/// the file or streaming formats, the dictionary ids are found in the
/// DictionaryBatch messages
func (rcv *DictionaryEncoding) Id() int64 {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetInt64(o + rcv._tab.Pos)
}
return 0
}
/// The known dictionary id in the application where this data is used. In
/// the file or streaming formats, the dictionary ids are found in the
/// DictionaryBatch messages
func (rcv *DictionaryEncoding) MutateId(n int64) bool {
return rcv._tab.MutateInt64Slot(4, n)
}
/// The dictionary indices are constrained to be positive integers. If this
/// field is null, the indices must be signed int32
func (rcv *DictionaryEncoding) IndexType(obj *Int) *Int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(Int)
}
obj.Init(rcv._tab.Bytes, x)
return obj
}
return nil
}
/// The dictionary indices are constrained to be positive integers. If this
/// field is null, the indices must be signed int32
/// By default, dictionaries are not ordered, or the order does not have
/// semantic meaning. In some statistical, applications, dictionary-encoding
/// is used to represent ordered categorical data, and we provide a way to
/// preserve that metadata here
func (rcv *DictionaryEncoding) IsOrdered() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
/// By default, dictionaries are not ordered, or the order does not have
/// semantic meaning. In some statistical, applications, dictionary-encoding
/// is used to represent ordered categorical data, and we provide a way to
/// preserve that metadata here
func (rcv *DictionaryEncoding) MutateIsOrdered(n bool) bool {
return rcv._tab.MutateBoolSlot(8, n)
}
func DictionaryEncodingStart(builder *flatbuffers.Builder) {
builder.StartObject(3)
}
func DictionaryEncodingAddId(builder *flatbuffers.Builder, id int64) {
builder.PrependInt64Slot(0, id, 0)
}
func DictionaryEncodingAddIndexType(builder *flatbuffers.Builder, indexType flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(1, flatbuffers.UOffsetT(indexType), 0)
}
func DictionaryEncodingAddIsOrdered(builder *flatbuffers.Builder, isOrdered bool) {
builder.PrependBoolSlot(2, isOrdered, false)
}
func DictionaryEncodingEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -1,65 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
type Duration struct {
_tab flatbuffers.Table
}
func GetRootAsDuration(buf []byte, offset flatbuffers.UOffsetT) *Duration {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Duration{}
x.Init(buf, n+offset)
return x
}
func (rcv *Duration) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Duration) Table() flatbuffers.Table {
return rcv._tab
}
func (rcv *Duration) Unit() TimeUnit {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.GetInt16(o + rcv._tab.Pos)
}
return 1
}
func (rcv *Duration) MutateUnit(n TimeUnit) bool {
return rcv._tab.MutateInt16Slot(4, n)
}
func DurationStart(builder *flatbuffers.Builder) {
builder.StartObject(1)
}
func DurationAddUnit(builder *flatbuffers.Builder, unit int16) {
builder.PrependInt16Slot(0, unit, 1)
}
func DurationEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -1,33 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
/// ----------------------------------------------------------------------
/// Endianness of the platform producing the data
type Endianness = int16
const (
EndiannessLittle Endianness = 0
EndiannessBig Endianness = 1
)
var EnumNamesEndianness = map[Endianness]string{
EndiannessLittle:"Little",
EndiannessBig:"Big",
}

View File

@@ -1,188 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
/// ----------------------------------------------------------------------
/// A field represents a named column in a record / row batch or child of a
/// nested type.
type Field struct {
_tab flatbuffers.Table
}
func GetRootAsField(buf []byte, offset flatbuffers.UOffsetT) *Field {
n := flatbuffers.GetUOffsetT(buf[offset:])
x := &Field{}
x.Init(buf, n+offset)
return x
}
func (rcv *Field) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *Field) Table() flatbuffers.Table {
return rcv._tab
}
/// Name is not required, in i.e. a List
func (rcv *Field) Name() []byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(4))
if o != 0 {
return rcv._tab.ByteVector(o + rcv._tab.Pos)
}
return nil
}
/// Name is not required, in i.e. a List
/// Whether or not this field can contain nulls. Should be true in general.
func (rcv *Field) Nullable() bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(6))
if o != 0 {
return rcv._tab.GetBool(o + rcv._tab.Pos)
}
return false
}
/// Whether or not this field can contain nulls. Should be true in general.
func (rcv *Field) MutateNullable(n bool) bool {
return rcv._tab.MutateBoolSlot(6, n)
}
func (rcv *Field) TypeType() byte {
o := flatbuffers.UOffsetT(rcv._tab.Offset(8))
if o != 0 {
return rcv._tab.GetByte(o + rcv._tab.Pos)
}
return 0
}
func (rcv *Field) MutateTypeType(n byte) bool {
return rcv._tab.MutateByteSlot(8, n)
}
/// This is the type of the decoded value if the field is dictionary encoded.
func (rcv *Field) Type(obj *flatbuffers.Table) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(10))
if o != 0 {
rcv._tab.Union(obj, o)
return true
}
return false
}
/// This is the type of the decoded value if the field is dictionary encoded.
/// Present only if the field is dictionary encoded.
func (rcv *Field) Dictionary(obj *DictionaryEncoding) *DictionaryEncoding {
o := flatbuffers.UOffsetT(rcv._tab.Offset(12))
if o != 0 {
x := rcv._tab.Indirect(o + rcv._tab.Pos)
if obj == nil {
obj = new(DictionaryEncoding)
}
obj.Init(rcv._tab.Bytes, x)
return obj
}
return nil
}
/// Present only if the field is dictionary encoded.
/// children apply only to nested data types like Struct, List and Union. For
/// primitive types children will have length 0.
func (rcv *Field) Children(obj *Field, j int) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
if o != 0 {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4
x = rcv._tab.Indirect(x)
obj.Init(rcv._tab.Bytes, x)
return true
}
return false
}
func (rcv *Field) ChildrenLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(14))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
/// children apply only to nested data types like Struct, List and Union. For
/// primitive types children will have length 0.
/// User-defined metadata
func (rcv *Field) CustomMetadata(obj *KeyValue, j int) bool {
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
if o != 0 {
x := rcv._tab.Vector(o)
x += flatbuffers.UOffsetT(j) * 4
x = rcv._tab.Indirect(x)
obj.Init(rcv._tab.Bytes, x)
return true
}
return false
}
func (rcv *Field) CustomMetadataLength() int {
o := flatbuffers.UOffsetT(rcv._tab.Offset(16))
if o != 0 {
return rcv._tab.VectorLen(o)
}
return 0
}
/// User-defined metadata
func FieldStart(builder *flatbuffers.Builder) {
builder.StartObject(7)
}
func FieldAddName(builder *flatbuffers.Builder, name flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(name), 0)
}
func FieldAddNullable(builder *flatbuffers.Builder, nullable bool) {
builder.PrependBoolSlot(1, nullable, false)
}
func FieldAddTypeType(builder *flatbuffers.Builder, typeType byte) {
builder.PrependByteSlot(2, typeType, 0)
}
func FieldAddType(builder *flatbuffers.Builder, type_ flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(type_), 0)
}
func FieldAddDictionary(builder *flatbuffers.Builder, dictionary flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(4, flatbuffers.UOffsetT(dictionary), 0)
}
func FieldAddChildren(builder *flatbuffers.Builder, children flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(5, flatbuffers.UOffsetT(children), 0)
}
func FieldStartChildrenVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func FieldAddCustomMetadata(builder *flatbuffers.Builder, customMetadata flatbuffers.UOffsetT) {
builder.PrependUOffsetTSlot(6, flatbuffers.UOffsetT(customMetadata), 0)
}
func FieldStartCustomMetadataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT {
return builder.StartVector(4, numElems, 4)
}
func FieldEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
return builder.EndObject()
}

View File

@@ -1,76 +0,0 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by the FlatBuffers compiler. DO NOT EDIT.
package flatbuf
import (
flatbuffers "github.com/google/flatbuffers/go"
)
/// ----------------------------------------------------------------------
/// Data structures for describing a table row batch (a collection of
/// equal-length Arrow arrays)
/// Metadata about a field at some level of a nested type tree (but not
/// its children).
///
/// For example, a List<Int16> with values [[1, 2, 3], null, [4], [5, 6], null]
/// would have {length: 5, null_count: 2} for its List node, and {length: 6,
/// null_count: 0} for its Int16 node, as separate FieldNode structs
type FieldNode struct {
_tab flatbuffers.Struct
}
func (rcv *FieldNode) Init(buf []byte, i flatbuffers.UOffsetT) {
rcv._tab.Bytes = buf
rcv._tab.Pos = i
}
func (rcv *FieldNode) Table() flatbuffers.Table {
return rcv._tab.Table
}
/// The number of value slots in the Arrow array at this level of a nested
/// tree
func (rcv *FieldNode) Length() int64 {
return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(0))
}
/// The number of value slots in the Arrow array at this level of a nested
/// tree
func (rcv *FieldNode) MutateLength(n int64) bool {
return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(0), n)
}
/// The number of observed nulls. Fields with null_count == 0 may choose not
/// to write their physical validity bitmap out as a materialized buffer,
/// instead setting the length of the bitmap buffer to 0.
func (rcv *FieldNode) NullCount() int64 {
return rcv._tab.GetInt64(rcv._tab.Pos + flatbuffers.UOffsetT(8))
}
/// The number of observed nulls. Fields with null_count == 0 may choose not
/// to write their physical validity bitmap out as a materialized buffer,
/// instead setting the length of the bitmap buffer to 0.
func (rcv *FieldNode) MutateNullCount(n int64) bool {
return rcv._tab.MutateInt64(rcv._tab.Pos+flatbuffers.UOffsetT(8), n)
}
func CreateFieldNode(builder *flatbuffers.Builder, length int64, nullCount int64) flatbuffers.UOffsetT {
builder.Prep(8, 16)
builder.PrependInt64(nullCount)
builder.PrependInt64(length)
return builder.Offset()
}

Some files were not shown because too many files have changed in this diff Show More