Compare commits

...

21 Commits

Author SHA1 Message Date
Simon Bruder 327235c451
be less silly next time (hard coded version number where it is dynamic)
continuous-integration/drone/push Build is passing Details
2019-06-23 00:15:18 +00:00
Simon Bruder d63397b1ed
make docker image much smaller
continuous-integration/drone/push Build was killed Details
2019-06-02 09:05:11 +00:00
Simon Bruder 1da5439358 add drone config
continuous-integration/drone/push Build is passing Details
2019-03-25 16:25:41 +01:00
Simon Bruder 58c9465add always use latest alpine version 2019-03-25 16:24:07 +01:00
Matthieu Grieger dff929ddc9 Update README.md 2017-05-20 18:04:02 -07:00
Matthieu Grieger 138c1008eb Fixed YouTube playback offsets 2016-11-05 21:30:42 -07:00
Matthieu Grieger 2f6bda5018 Update version number and changelog 2016-11-05 19:41:58 -07:00
Matthieu Grieger a1c5399223 https://github.com/matthieugrieger/mumbledj/issues/182: Added back track/playlist submitter immediate skipping 2016-11-05 19:39:31 -07:00
Matthieu Grieger e1e3a334cd Fix https://github.com/matthieugrieger/mumbledj/issues/180: Panic on playlist with private video 2016-11-05 19:22:58 -07:00
Matthieu Grieger 51db9c3061 Fix https://github.com/matthieugrieger/mumbledj/issues/176: Empty IDs for SoundCloud tracks 2016-08-22 20:20:41 -07:00
Matthieu Grieger 9222608962 Fixed https://github.com/matthieugrieger/mumbledj/issues/174: Fixed deadlock during track skip/finish 2016-08-21 17:58:11 -07:00
Matthieu Grieger 466e9189c6 Fix https://github.com/matthieugrieger/mumbledj/issues/172: Index out of range error during skip 2016-08-14 10:00:38 -07:00
Matthieu Grieger 786ab8c3d6 Small stylistic and spelling changes 2016-07-11 16:08:16 -07:00
Matthieu Grieger f918d2397d Updated vendored dependencies 2016-07-11 16:03:02 -07:00
Gabriel Plassard 66be67719a Docker (#170)
* added dockerfile

* cleanup dockerfile

* update Dockerfile and create raspberry dockerfile

* doc & aria2
2016-07-11 15:57:47 -07:00
Matthieu Grieger 0a4d0aead1 Implemented register command 2016-07-10 21:09:54 -07:00
Matthieu Grieger 32167c1294 p12 files can now be provided to the bot to authenticate as a registered user 2016-07-10 20:41:51 -07:00
Matthieu Grieger 5434077d73 Remove crypto/pkcs12 2016-07-10 20:15:15 -07:00
Matthieu Grieger 1e174fde46 Update dependencies, add crypto/pkcs12 2016-07-04 10:06:28 -07:00
Matthieu Grieger 3de4917972 Potential fix for PEM IP SANs issue 2016-07-01 18:34:43 -07:00
Matthieu Grieger d0becb9c10 Fix https://github.com/matthieugrieger/mumbledj/issues/162: Key is no longer mistakenly overwritten by cert 2016-06-29 19:08:01 -07:00
69 changed files with 1877 additions and 729 deletions

1
.dockerignore Normal file
View File

@ -0,0 +1 @@
Dockerfile

13
.drone.yml Normal file
View File

@ -0,0 +1,13 @@
kind: pipeline
name: default
steps:
- name: docker
image: plugins/docker
settings:
registry: r.sbruder.de
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: r.sbruder.de/mumbledj

View File

@ -1,6 +1,36 @@
MumbleDJ Changelog
==================
### November 5, 2016 -- `v3.2.1`
* Fixed YouTube video offsets. Now YouTube URLs with `?t=<timestamp>` at the end will start the audio playback at the appropriate position.
### November 5, 2016 -- `v3.2.0`
* Fixed a Go panic that would occur when a YouTube playlist contained a private video.
* Added back immediate skipping for tracks/playlists that are skipped by the submitter. This was a feature that was present in the last major version of MumbleDJ but was forgotten when rewriting the bot (sorry!).
### August 22, 2016 -- `v3.1.4`
* Fixed a SoundCloud API response parsing issue that would result in empty IDs for tracks.
* Fixed the startup check for SoundCloud API.
### August 21, 2016 -- `v3.1.3`
* Fixed a deadlock that would occur during the transition from the first to second track in a queue.
### August 14, 2016 -- `v3.1.2`
* Fixed an index out of range crash in the queue skipping function.
### July 11, 2016 -- `v3.1.1`
* Updated vendored dependencies to hopefully address the following issue: https://github.com/matthieugrieger/mumbledj/issues/169.
### July 10, 2016 -- `v3.1.0`
* File path for user `p12` certificate can now be provided for authenticating as a registered user via the `--p12` commandline flag or the `connection.user_p12` configuration value.
* Added `!register` command for registering the bot on the server.
### July 1, 2016 -- `v3.0.11`
* Potential fix for an issue with IP SANs on PEM certs.
### June 29, 2016 -- `v3.0.10`
* Fixed issue related to PEM keys being overwritten by PEM certs.
### June 28, 2016 -- `v3.0.9`
* Queue is now reset after disconnecting from the server to avoid unpredictable behavior.

39
Dockerfile Normal file
View File

@ -0,0 +1,39 @@
FROM golang:alpine as builder
RUN apk add --no-cache \
build-base \
opus-dev
COPY . /go/src/github.com/matthieugrieger/mumbledj
WORKDIR /go/src/github.com/matthieugrieger/mumbledj
RUN go get -v \
&& go build -v -ldflags="-s -w"
FROM alpine
RUN adduser -D mumbledj
RUN apk add --no-cache \
aria2 \
libressl \
python2
RUN wget -O /usr/bin/youtube-dl https://yt-dl.org/downloads/latest/youtube-dl \
&& chmod +x /usr/bin/youtube-dl
RUN wget https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz \
&& tar xvf ffmpeg-git-amd64-static.tar.xz '*/ffmpeg' || true \
&& mv ffmpeg-git-*-amd64-static/ffmpeg /usr/bin/ffmpeg \
&& rm -rf ffmpeg-git-* \
&& apk add --no-cache upx \
&& upx /usr/bin/ffmpeg \
&& apk del upx
COPY --from=builder /go/src/github.com/matthieugrieger/mumbledj/mumbledj /usr/bin/mumbledj
COPY config.yaml /home/mumbledj/.config/mumbledj/config.yaml
USER mumbledj
ENTRYPOINT ["/usr/bin/mumbledj"]

View File

@ -3,6 +3,8 @@
<p align="center"><b>A Mumble bot that plays audio fetched from various media websites.</b></p>
<p align="center"><a href="https://travis-ci.org/matthieugrieger/mumbledj"><img src="https://travis-ci.org/matthieugrieger/mumbledj.svg?branch=master"/></a> <a href="https://raw.githubusercontent.com/matthieugrieger/mumbledj/master/LICENSE"><img src="https://img.shields.io/badge/license-MIT-blue.svg"/></a> <a href="https://github.com/matthieugrieger/mumbledj/releases"><img src="https://img.shields.io/github/release/matthieugrieger/mumbledj.svg"/></a> <a href="https://goreportcard.com/report/github.com/matthieugrieger/mumbledj"><img src="https://goreportcard.com/badge/github.com/matthieugrieger/mumbledj"/></a> <a href="https://codecov.io/gh/matthieugrieger/mumbledj"><img src="https://img.shields.io/codecov/c/github/matthieugrieger/mumbledj.svg"/></a> <a href="https://gitter.im/matthieugrieger/mumbledj"><img src="https://img.shields.io/gitter/room/matthieugrieger/mumbledj.svg" /></a></p>
<p align="center"><b>Unfortunately, this project is no longer maintained. Don't expect any responses on bug reports, feature requests, etc. Forks are welcome!</b></p>
## Table of Contents
* [Features](#features)
@ -13,6 +15,7 @@
* [Via `go get`](#via-go-get-recommended)
* [Pre-compiled Binaries](#pre-compiled-binaries-easiest)
* [From Source](#from-source)
* [Docker](#docker)
* [Usage](#usage)
* [Commands](#commands)
* [Contributing](#contributing)
@ -57,7 +60,7 @@ A YouTube API key must be present in your configuration file in order to use the
**5)** Add the IP address of the machine MumbleDJ will run on in the box that appears (this is optional, but improves security). Click "Create".
**6)** You should now see that an API key has been generated. Copy/paste this API key into the configuration file located at `$HOME/.config/mumbledj/mumbledj.yaml`.
**6)** You should now see that an API key has been generated. Copy/paste this API key into the configuration file located at `$HOME/.config/mumbledj/mumbledj.yaml`.
#### SoundCloud API Key
A SoundCloud client ID must be present in your configuration file in order to use the SoundCloud service within the bot. Below is a guide for retrieving a client ID:
@ -103,6 +106,35 @@ This will place a compiled `mumbledj` binary in the cloned directory if successf
sudo make install
```
### Docker
You can also use [Docker](https://www.docker.com) to run MumbleDJ.
First you need to clone the MumbleDJ repository to your machine:
```
git clone https://github.com/matthieugrieger/mumbledj.git
```
Assuming you have [Docker installed](https://www.docker.com/products/docker), you will have to build the image:
```
docker build -t mumbledj .
```
And then you can run it, passing the configuration through the command line:
```
docker run --rm --name=mumbledj mumbledj --server=SERVER --api_keys.youtube=YOUR_YOUTUBE_API_KEY --api_keys.soundcloud=YOUR_SOUNDCLOUD_API_KEY
```
In order to run the process as a daemon and restart it automatically on reboot you can use:
```
docker run -d --restart=unless-stopped --name=mumbledj mumbledj --server=SERVER --api_keys.youtube=YOUR_YOUTUBE_API_KEY --api_keys.soundcloud=YOUR_SOUNDCLOUD_API_KEY
```
You can also install Docker on a [Raspberry Pi](https://www.raspberrypi.org/) for instance with [hypriot](http://blog.hypriot.com/getting-started-with-docker-on-your-arm-device/) or with [archlinux](https://archlinuxarm.org/packages/arm/docker). You just need to build the ARM image:
```
docker build -f raspberry.Dockerfile -t mumbledj .
```
## Usage
MumbleDJ is a compiled program that is executed via a terminal.
@ -114,25 +146,26 @@ NAME:
USAGE:
mumbledj [global options] command [command options] [arguments...]
VERSION:
3.0.0-alpha
v3.1.0
COMMANDS:
GLOBAL OPTIONS:
--config value, -c value location of MumbleDJ configuration file (default: "$HOME/.config/mumbledj/mumbledj.yaml")
--server value, -s value address of Mumble server to connect to (default: "127.0.0.1")
--port value, -o value port of Mumble server to connect to (default: "64738")
--username value, -u value username for the bot (default: "MumbleDJ")
--password value, -p value password for the Mumble server
--channel value, -n value channel the bot enters after connecting to the Mumble server
--cert value, -e value path to PEM certificate
--key value, -k value path to PEM key
--accesstokens value, -a value list of access tokens separated by spaces
--insecure, -i if present, the bot will not check Mumble certs for consistency
--debug, -d if present, all debug messages will be shown
--help, -h show help
--version, -v print the version
--config value, -c value location of MumbleDJ configuration file (default: "/home/matthieu/.config/mumbledj/config.yaml")
--server value, -s value address of Mumble server to connect to (default: "127.0.0.1")
--port value, -o value port of Mumble server to connect to (default: "64738")
--username value, -u value username for the bot (default: "MumbleDJ")
--password value, -p value password for the Mumble server
--channel value, -n value channel the bot enters after connecting to the Mumble server
--p12 value path to user p12 file for authenticating as a registered user
--cert value, -e value path to PEM certificate
--key value, -k value path to PEM key
--accesstokens value, -a value list of access tokens separated by spaces
--insecure, -i if present, the bot will not check Mumble certs for consistency
--debug, -d if present, all debug messages will be shown
--help, -h show help
--version, -v print the version
```
@ -251,6 +284,13 @@ Keep in mind that values that contain commas (such as `"SuperUser,Matt"`) will b
* __Admin-only by default__: No
* __Example__: `!pause`
### register
* __Description__: Registers the bot on the server.
* __Default Aliases__: register, reg
* __Arguments__: None
* __Admin-only by default__: Yes
* __Example__: `!register`
### reload
* __Description__: Reloads the configuration file.
* __Default Aliases__: reload, r

File diff suppressed because one or more lines are too long

View File

@ -40,6 +40,7 @@ func SetDefaultConfig() {
viper.SetDefault("connection.port", 64738)
viper.SetDefault("connection.password", "")
viper.SetDefault("connection.username", "MumbleDJ")
viper.SetDefault("connection.user_p12", "")
viper.SetDefault("connection.insecure", false)
viper.SetDefault("connection.cert", "")
viper.SetDefault("connection.key", "")
@ -156,6 +157,12 @@ func SetDefaultConfig() {
viper.SetDefault("commands.pause.messages.no_audio_error", "Either the audio is already paused, or there are no tracks in the queue.")
viper.SetDefault("commands.pause.messages.paused", "<b>%s</b> has paused audio playback.")
viper.SetDefault("commands.register.aliases", []string{"register", "reg"})
viper.SetDefault("commands.register.is_admin", true)
viper.SetDefault("commands.register.description", "Registers the bot on the server.")
viper.SetDefault("commands.register.messages.already_registered_error", "I am already registered on the server.")
viper.SetDefault("commands.register.messages.registered", "I am now registered on the server.")
viper.SetDefault("commands.reload.aliases", []string{"reload", "r"})
viper.SetDefault("commands.reload.is_admin", true)
viper.SetDefault("commands.reload.description", "Reloads the configuration file.")
@ -189,6 +196,7 @@ func SetDefaultConfig() {
viper.SetDefault("commands.skip.description", "Places a vote to skip the current track.")
viper.SetDefault("commands.skip.messages.already_voted_error", "You have already voted to skip this track.")
viper.SetDefault("commands.skip.messages.voted", "<b>%s</b> has voted to skip the current track.")
viper.SetDefault("commands.skip.messages.submitter_voted", "<b>%s</b>, the submitter of this track, has voted to skip. Skipping immediately.")
viper.SetDefault("commands.skipplaylist.aliases", []string{"skipplaylist", "sp"})
viper.SetDefault("commands.skipplaylist.is_admin", false)
@ -196,6 +204,7 @@ func SetDefaultConfig() {
viper.SetDefault("commands.skipplaylist.messages.no_playlist_error", "The current track is not part of a playlist.")
viper.SetDefault("commands.skipplaylist.messages.already_voted_error", "You have already voted to skip this playlist.")
viper.SetDefault("commands.skipplaylist.messages.voted", "<b>%s</b> has voted to skip the current playlist.")
viper.SetDefault("commands.skipplaylist.messages.submitter_voted", "<b>%s</b>, the submitter of this playlist, has voted to skip. Skipping immediately.")
viper.SetDefault("commands.toggleshuffle.aliases", []string{"toggleshuffle", "toggleshuf", "togshuf", "tsh"})
viper.SetDefault("commands.toggleshuffle.is_admin", true)

View File

@ -11,7 +11,10 @@ import (
"crypto/tls"
"errors"
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
"strings"
"time"
@ -193,13 +196,48 @@ func (dj *MumbleDJ) Connect() error {
// Initialize key pair if needed.
if viper.GetBool("connection.insecure") {
dj.TLSConfig.InsecureSkipVerify = true
} else {
dj.TLSConfig.ServerName = viper.GetString("connection.address")
if viper.GetString("connection.cert") != "" {
if viper.GetString("connection.key") == "" {
viper.Set("connection.key", viper.GetString("connection.cert"))
}
if certificate, err := tls.LoadX509KeyPair(viper.GetString("connection.cert"), viper.GetString("connection.key")); err == nil {
dj.TLSConfig.Certificates = append(dj.TLSConfig.Certificates, certificate)
} else {
return err
}
}
}
if viper.GetString("connection.cert") != "" {
if viper.GetString("connection.key") != "" {
viper.Set("connection.key", viper.GetString("connection.cert"))
// Add user p12 cert if needed.
if viper.GetString("connection.user_p12") != "" {
if _, err := os.Stat(viper.GetString("connection.user_p12")); os.IsNotExist(err) {
return err
}
if certificate, err := tls.LoadX509KeyPair(viper.GetString("connection.cert"), viper.GetString("connection.key")); err == nil {
// Create temporary directory for converted p12 file.
dir, err := ioutil.TempDir("", "mumbledj")
if err != nil {
return err
}
defer os.RemoveAll(dir)
// Create temporary mumbledj.crt.pem from p12 file.
command := exec.Command("openssl", "pkcs12", "-password", "pass:", "-in", viper.GetString("connection.user_p12"), "-out", dir+"/mumbledj.crt.pem", "-clcerts", "-nokeys")
if err := command.Run(); err != nil {
return err
}
// Create temporary mumbledj.key.pem from p12 file.
command = exec.Command("openssl", "pkcs12", "-password", "pass:", "-in", viper.GetString("connection.user_p12"), "-out", dir+"/mumbledj.key.pem", "-nocerts", "-nodes")
if err := command.Run(); err != nil {
return err
}
if certificate, err := tls.LoadX509KeyPair(dir+"/mumbledj.crt.pem", dir+"/mumbledj.key.pem"); err == nil {
dj.TLSConfig.Certificates = append(dj.TLSConfig.Certificates, certificate)
} else {
return err

View File

@ -199,7 +199,7 @@ func (q *Queue) Skip() {
q.mutex.Lock()
// If caching is disabled, delete the track from disk.
if !viper.GetBool("cache.enabled") {
if len(q.Queue) != 0 && !viper.GetBool("cache.enabled") {
DJ.YouTubeDL.Delete(q.Queue[0])
}

View File

@ -58,6 +58,10 @@ func PerformStartupChecks() {
if err := checkAria2Installation(); err != nil {
logrus.Warnln("aria2 is not installed or is not discoverable in $PATH. The bot will still partially work, but some services will not work properly.")
}
if err := checkOpenSSLInstallation(); err != nil {
logrus.Warnln("openssl is not installed or is not discoverable in $PATH. p12 certificate files will not work.")
}
}
func checkYouTubeDLInstallation() error {
@ -95,3 +99,12 @@ func checkAria2Installation() error {
}
return nil
}
func checkOpenSSLInstallation() error {
logrus.Infoln("Checking openssl installation...")
command := exec.Command("openssl", "version")
if err := command.Run(); err != nil {
return errors.New("openssl is not properly installed")
}
return nil
}

View File

@ -35,6 +35,7 @@ func init() {
new(NumCachedCommand),
new(NumTracksCommand),
new(PauseCommand),
new(RegisterCommand),
new(ReloadCommand),
new(ResetCommand),
new(ResumeCommand),

53
commands/register.go Normal file
View File

@ -0,0 +1,53 @@
/*
* MumbleDJ
* By Matthieu Grieger
* commands/register.go
* Copyright (c) 2016 Matthieu Grieger (MIT License)
*/
package commands
import (
"errors"
"github.com/layeh/gumble/gumble"
"github.com/spf13/viper"
)
// RegisterCommand is a command that registers the bot on the server.
type RegisterCommand struct{}
// Aliases returns the current aliases for the command.
func (c *RegisterCommand) Aliases() []string {
return viper.GetStringSlice("commands.register.aliases")
}
// Description returns the description for the command.
func (c *RegisterCommand) Description() string {
return viper.GetString("commands.register.description")
}
// IsAdminCommand returns true if the command is only for admin use, and
// returns false otherwise.
func (c *RegisterCommand) IsAdminCommand() bool {
return viper.GetBool("commands.register.is_admin")
}
// Execute executes the command with the given user and arguments.
// Return value descriptions:
// string: A message to be returned to the user upon successful execution.
// bool: Whether the message should be private or not. true = private,
// false = public (sent to whole channel).
// error: An error message to be returned upon unsuccessful execution.
// If no error has occurred, pass nil instead.
// Example return statement:
// return "This is a private message!", true, nil
func (c *RegisterCommand) Execute(user *gumble.User, args ...string) (string, bool, error) {
if DJ.Client.Self.IsRegistered() {
return "", true, errors.New(viper.GetString("commands.register.messages.already_registered_error"))
}
DJ.Client.Self.Register()
return viper.GetString("commands.register.messages.registered"), true, nil
}

View File

@ -0,0 +1,8 @@
/*
* MumbleDJ
* By Matthieu Grieger
* commands/register_test.go
* Copyright (c) 2016 Matthieu Grieger (MIT License)
*/
package commands

View File

@ -47,6 +47,11 @@ func (c *SkipCommand) Execute(user *gumble.User, args ...string) (string, bool,
if DJ.Queue.Length() == 0 {
return "", true, errors.New(viper.GetString("commands.common_messages.no_tracks_error"))
}
if DJ.Queue.GetTrack(0).GetSubmitter() == user.Name {
// The user who submitted the track is skipping, this means we skip this track immediately.
DJ.Queue.StopCurrent()
return fmt.Sprintf(viper.GetString("commands.skip.messages.submitter_voted"), user.Name), false, nil
}
if err := DJ.Skips.AddTrackSkip(user); err != nil {
return "", true, errors.New(viper.GetString("commands.skip.messages.already_voted_error"))
}

View File

@ -58,6 +58,10 @@ func (c *SkipPlaylistCommand) Execute(user *gumble.User, args ...string) (string
if playlist := currentTrack.GetPlaylist(); playlist == nil {
return "", true, errors.New(viper.GetString("commands.skipplaylist.messages.no_playlist_error"))
}
if currentTrack.GetPlaylist().GetSubmitter() == user.Name {
DJ.Queue.SkipPlaylist()
return fmt.Sprintf(viper.GetString("commands.skipplaylist.messages.submitter_voted"), user.Name), false, nil
}
if err := DJ.Skips.AddPlaylistSkip(user); err != nil {
return "", true, errors.New(viper.GetString("commands.skipplaylist.messages.already_voted_error"))
}

View File

@ -63,6 +63,10 @@ connection:
# Username for MumbleDJ.
username: "MumbleDJ"
# Filepath to user p12 file for authenticating as a registered user.
# NOTE: If no p12 file is needed, set to empty string ("").
user_p12: ""
# Should the bot attempt an insecure connection?
# An insecure connection does not verify the certificate of the server for
# consistency. It is best to leave this on, but disable it if you are having
@ -260,7 +264,7 @@ commands:
messages:
no_channel_provided_error: "A destination channel must be supplied to move the bot."
channel_doesnt_exist_error: "The provided channel does not exist."
move_successful: "You have successfully moved the bot to <b>%s</b>."
move_successful: "You have successfully moved the bot to <b>%s</b>."
nexttrack:
aliases:
@ -302,6 +306,16 @@ commands:
no_audio_error: "Either the audio is already paused, or there are no tracks in the queue."
paused: "<b>%s</b> has paused audio playback."
register:
aliases:
- "register"
- "reg"
is_admin: true
description: "Registers the bot on the server."
messages:
already_registered_error: "I am already registered on the server."
registered: "I am now registered on the server."
reload:
aliases:
- "reload"
@ -360,6 +374,7 @@ commands:
messages:
already_voted_error: "You have already voted to skip this track."
voted: "<b>%s</b> has voted to skip the current track."
submitter_voted: "<b>%s</b>, the submitter of this track, has voted to skip. Skipping immediately."
skipplaylist:
aliases:
@ -371,6 +386,7 @@ commands:
no_playlist_error: "The current track is not part of a playlist."
already_voted_error: "You have already voted to skip this playlist."
voted: "<b>%s</b> has voted to skip the current playlist."
submitter_voted: "<b>%s</b>, the submitter of this playlist, has voted to skip. Skipping immediately."
toggleshuffle:
aliases:
@ -404,4 +420,4 @@ commands:
parsing_error: "The requested volume could not be parsed."
out_of_range_error: "Volumes must be between the values <b>%.2f</b> and <b>%.2f</b>."
current_volume: "The current volume is <b>%.2f</b>."
volume_changed: "<b>%s</b> has changed the volume to <b>%.2f</b>."
volume_changed: "<b>%s</b> has changed the volume to <b>%.2f</b>."

40
glide.lock generated
View File

@ -1,20 +1,20 @@
hash: b68f7c8a3b59d7dac3e12321ed6a2265b553c2856ae70e0ed5e960ba8412f8d8
updated: 2016-06-21T09:22:02.569941705-07:00
updated: 2016-07-11T16:01:20.19606261-07:00
imports:
- name: github.com/antonholmquist/jason
version: ""
version: c23cef7eaa75a6a5b8810120e167bd590d8fd2ab
- name: github.com/BurntSushi/toml
version: ""
version: bbd5bb678321a0d6e58f1099321dfa73391c1b6f
- name: github.com/ChannelMeter/iso8601duration
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: 8da3af7a2a61a4eb5ae9bddec06bf637fa9593da
- name: github.com/fsnotify/fsnotify
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: a8a77c9133d2d6fd8334f3260d06f60e8d80a5fb
- name: github.com/golang/protobuf
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: 3852dcfda249c2097355a6aabb199a28d97b30df
subpackages:
- proto
- name: github.com/hashicorp/hcl
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: 364df430845abef160a0bfb3a59979f746bf4956
subpackages:
- hcl/ast
- hcl/parser
@ -25,9 +25,9 @@ imports:
- json/scanner
- json/token
- name: github.com/layeh/gopus
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: 867541549ca5f8b4db2b92fd1dded8711256a27d
- name: github.com/layeh/gumble
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: f0a4a2992fa9a969ef90d673374bc63a9b7948ad
subpackages:
- gumble
- gumbleffmpeg
@ -36,27 +36,27 @@ imports:
- gumble/MumbleProto
- gumble/varint
- name: github.com/magiconair/properties
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: e2f061ecfdaca9f35b2e2c12346ffc526f138137
- name: github.com/mitchellh/mapstructure
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: d2dd0262208475919e1a362f675cfc0e7c10e905
- name: github.com/Sirupsen/logrus
version: ""
version: 4b6ea7319e214d98c938f12692336f7ca9348d6b
- name: github.com/spf13/cast
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: 27b586b42e29bec072fe7379259cc719e1289da6
- name: github.com/spf13/jwalterweatherman
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: 33c24e77fb80341fe7130ee7c594256ff08ccc46
- name: github.com/spf13/pflag
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: 367864438f1b1a3c7db4da06a2f55b144e6784e0
- name: github.com/spf13/viper
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: c1ccc378a054ea8d4e38d8c67f6938d4760b53dd
- name: github.com/stretchr/testify
version: ""
version: f390dcf405f7b83c997eac1b06768bb9f44dec18
- name: github.com/urfave/cli
version: ""
version: 01857ac33766ce0c93856370626f9799281c14f4
- name: golang.org/x/sys
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: a408501be4d17ee978c04a618e7a1b22af058c0e
subpackages:
- unix
- name: gopkg.in/yaml.v2
version: 50c5e6cb61d6f5a3c449ab0b12f1996160626a94
version: a83829b6f1293c91addabc89d0571c246397bbf4
devImports: []

10
main.go
View File

@ -32,7 +32,7 @@ func init() {
services.DJ = DJ
bot.DJ = DJ
DJ.Version = "v3.0.9"
DJ.Version = "v3.2.1"
logrus.SetLevel(logrus.WarnLevel)
}
@ -73,6 +73,11 @@ func main() {
Value: "",
Usage: "channel the bot enters after connecting to the Mumble server",
},
cli.StringFlag{
Name: "p12",
Value: "",
Usage: "path to user p12 file for authenticating as a registered user",
},
cli.StringFlag{
Name: "cert, e",
Value: "",
@ -156,6 +161,9 @@ func main() {
if c.GlobalIsSet("channel") {
viper.Set("defaults.channel", c.String("channel"))
}
if c.GlobalIsSet("p12") {
viper.Set("connection.user_p12", c.String("p12"))
}
if c.GlobalIsSet("cert") {
viper.Set("connection.cert", c.String("cert"))
}

20
raspberry.Dockerfile Normal file
View File

@ -0,0 +1,20 @@
FROM hypriot/rpi-alpine-scratch:v3.3
ENV GOPATH=/
RUN echo "https://dl-cdn.alpinelinux.org/alpine/v3.3/community" >> /etc/apk/repositories
RUN apk add --update ca-certificates go ffmpeg make build-base opus-dev python aria2
RUN apk upgrade
RUN wget https://yt-dl.org/downloads/latest/youtube-dl -O /bin/youtube-dl && chmod a+x /bin/youtube-dl
COPY . /src/github.com/matthieugrieger/mumbledj
COPY config.yaml /root/.config/mumbledj/config.yaml
WORKDIR /src/github.com/matthieugrieger/mumbledj
RUN make
RUN make install
RUN apk del go make build-base && rm -rf /var/cache/apk/*
ENTRYPOINT ["/usr/local/bin/mumbledj"]

View File

@ -52,7 +52,7 @@ func (sc *SoundCloud) CheckAPIKey() error {
if viper.GetString("api_keys.soundcloud") == "" {
return errors.New("No SoundCloud API key has been provided")
}
url := "http://api.soundcloud.com/tracks/vjflzpbkmerb?client_id=%s"
url := "http://api.soundcloud.com/tracks/13158665?client_id=%s"
response, err := http.Get(fmt.Sprintf(url, viper.GetString("api_keys.soundcloud")))
defer response.Body.Close()
if err != nil {
@ -162,7 +162,8 @@ func (sc *SoundCloud) GetTracks(url string, submitter *gumble.User) ([]interface
func (sc *SoundCloud) getTrack(obj *jason.Object, offset time.Duration, submitter *gumble.User) (bot.Track, error) {
title, _ := obj.GetString("title")
id, _ := obj.GetString("id")
idInt, _ := obj.GetInt64("id")
id := strconv.FormatInt(idInt, 10)
url, _ := obj.GetString("permalink_url")
author, _ := obj.GetString("user", "username")
authorURL, _ := obj.GetString("user", "permalink_url")

View File

@ -13,6 +13,8 @@ import (
"math"
"net/http"
"regexp"
"strings"
"time"
"github.com/ChannelMeter/iso8601duration"
"github.com/antonholmquist/jason"
@ -98,9 +100,12 @@ func (yt *YouTube) GetTracks(url string, submitter *gumble.User) ([]interfaces.T
tracks []interfaces.Track
)
dummyOffset, _ := time.ParseDuration("0s")
urlSplit := strings.Split(url, "?t=")
playlistURL = "https://www.googleapis.com/youtube/v3/playlists?part=snippet&id=%s&key=%s"
playlistItemsURL = "https://www.googleapis.com/youtube/v3/playlistItems?part=snippet,contentDetails&playlistId=%s&maxResults=%d&key=%s&pageToken=%s"
id, err = yt.getID(url)
id, err = yt.getID(urlSplit[0])
if err != nil {
return nil, err
}
@ -161,7 +166,7 @@ func (yt *YouTube) GetTracks(url string, submitter *gumble.User) ([]interfaces.T
// Unfortunately we have to execute another API call for each video as the YouTube API does not
// return video durations from the playlistItems endpoint...
newTrack, _ := yt.getTrack(videoID, submitter)
newTrack, _ := yt.getTrack(videoID, submitter, dummyOffset)
newTrack.Playlist = playlist
tracks = append(tracks, newTrack)
@ -182,7 +187,13 @@ func (yt *YouTube) GetTracks(url string, submitter *gumble.User) ([]interfaces.T
return tracks, nil
}
track, err = yt.getTrack(id, submitter)
// Submitter added a track!
offset := dummyOffset
if len(urlSplit) == 2 {
offset, _ = time.ParseDuration(urlSplit[1])
}
track, err = yt.getTrack(id, submitter, offset)
if err != nil {
return nil, err
}
@ -190,7 +201,7 @@ func (yt *YouTube) GetTracks(url string, submitter *gumble.User) ([]interfaces.T
return tracks, nil
}
func (yt *YouTube) getTrack(id string, submitter *gumble.User) (bot.Track, error) {
func (yt *YouTube) getTrack(id string, submitter *gumble.User, offset time.Duration) (bot.Track, error) {
var (
resp *http.Response
err error
@ -209,6 +220,9 @@ func (yt *YouTube) getTrack(id string, submitter *gumble.User) (bot.Track, error
return bot.Track{}, err
}
items, _ := v.GetObjectArray("items")
if len(items) == 0 {
return bot.Track{}, errors.New("This YouTube video is private")
}
item := items[0]
title, _ := item.GetString("snippet", "title")
thumbnail, _ := item.GetString("snippet", "thumbnails", "high", "url")
@ -218,15 +232,16 @@ func (yt *YouTube) getTrack(id string, submitter *gumble.User) (bot.Track, error
duration := durationConverted.ToDuration()
return bot.Track{
ID: id,
URL: "https://youtube.com/watch?v=" + id,
Title: title,
Author: author,
Submitter: submitter.Name,
Service: yt.ReadableName,
Filename: id + ".track",
ThumbnailURL: thumbnail,
Duration: duration,
Playlist: nil,
ID: id,
URL: "https://youtube.com/watch?v=" + id,
Title: title,
Author: author,
Submitter: submitter.Name,
Service: yt.ReadableName,
Filename: id + ".track",
ThumbnailURL: thumbnail,
Duration: duration,
PlaybackOffset: offset,
Playlist: nil,
}, nil
}

View File

@ -11,6 +11,7 @@
Adrien Bustany <adrien@bustany.org>
Amit Krishnan <amit.krishnan@oracle.com>
Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Bruno Bigras <bigras.bruno@gmail.com>
Caleb Spare <cespare@gmail.com>
Case Nelson <case@teammating.com>
Chris Howey <chris@howey.me> <howeyc@gmail.com>

View File

@ -1,5 +1,9 @@
# Changelog
## v1.3.1 / 2016-06-28
* windows: fix for double backslash when watching the root of a drive [#151](https://github.com/fsnotify/fsnotify/issues/151) (thanks @brunoqc)
## v1.3.0 / 2016-04-19
* Support linux/arm64 by [patching](https://go-review.googlesource.com/#/c/21971/) x/sys/unix and switching to to it from syscall (thanks @suihkulokki) [#135](https://github.com/fsnotify/fsnotify/pull/135)

View File

@ -306,7 +306,7 @@ func (w *Watcher) remWatch(pathname string) error {
watch.mask = 0
} else {
name := filepath.Base(pathname)
w.sendEvent(watch.path+"\\"+name, watch.names[name]&sysFSIGNORED)
w.sendEvent(filepath.Join(watch.path, name), watch.names[name]&sysFSIGNORED)
delete(watch.names, name)
}
return w.startRead(watch)
@ -316,7 +316,7 @@ func (w *Watcher) remWatch(pathname string) error {
func (w *Watcher) deleteWatch(watch *watch) {
for name, mask := range watch.names {
if mask&provisional == 0 {
w.sendEvent(watch.path+"\\"+name, mask&sysFSIGNORED)
w.sendEvent(filepath.Join(watch.path, name), mask&sysFSIGNORED)
}
delete(watch.names, name)
}
@ -453,7 +453,7 @@ func (w *Watcher) readEvents() {
raw := (*syscall.FileNotifyInformation)(unsafe.Pointer(&watch.buf[offset]))
buf := (*[syscall.MAX_PATH]uint16)(unsafe.Pointer(&raw.FileName))
name := syscall.UTF16ToString(buf[:raw.FileNameLength/2])
fullname := watch.path + "\\" + name
fullname := filepath.Join(watch.path, name)
var mask uint64
switch raw.Action {
@ -491,7 +491,7 @@ func (w *Watcher) readEvents() {
}
}
if raw.Action == syscall.FILE_ACTION_RENAMED_NEW_NAME {
fullname = watch.path + "\\" + watch.rename
fullname = filepath.Join(watch.path, watch.rename)
sendNameEvent()
}

View File

@ -510,41 +510,63 @@ func (m *Marshaler) marshalValue(out *errWriter, prop *proto.Properties, v refle
return out.err
}
// Unmarshaler is a configurable object for converting from a JSON
// representation to a protocol buffer object.
type Unmarshaler struct {
// Whether to allow messages to contain unknown fields, as opposed to
// failing to unmarshal.
AllowUnknownFields bool
}
// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
// This function is lenient and will decode any options permutations of the
// related Marshaler.
func UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
func (u *Unmarshaler) UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
inputValue := json.RawMessage{}
if err := dec.Decode(&inputValue); err != nil {
return err
}
return unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil)
return u.unmarshalValue(reflect.ValueOf(pb).Elem(), inputValue, nil)
}
// Unmarshal unmarshals a JSON object stream into a protocol
// buffer. This function is lenient and will decode any options
// permutations of the related Marshaler.
func (u *Unmarshaler) Unmarshal(r io.Reader, pb proto.Message) error {
dec := json.NewDecoder(r)
return u.UnmarshalNext(dec, pb)
}
// UnmarshalNext unmarshals the next protocol buffer from a JSON object stream.
// This function is lenient and will decode any options permutations of the
// related Marshaler.
func UnmarshalNext(dec *json.Decoder, pb proto.Message) error {
return new(Unmarshaler).UnmarshalNext(dec, pb)
}
// Unmarshal unmarshals a JSON object stream into a protocol
// buffer. This function is lenient and will decode any options
// permutations of the related Marshaler.
func Unmarshal(r io.Reader, pb proto.Message) error {
dec := json.NewDecoder(r)
return UnmarshalNext(dec, pb)
return new(Unmarshaler).Unmarshal(r, pb)
}
// UnmarshalString will populate the fields of a protocol buffer based
// on a JSON string. This function is lenient and will decode any options
// permutations of the related Marshaler.
func UnmarshalString(str string, pb proto.Message) error {
return Unmarshal(strings.NewReader(str), pb)
return new(Unmarshaler).Unmarshal(strings.NewReader(str), pb)
}
// unmarshalValue converts/copies a value into the target.
// prop may be nil.
func unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error {
func (u *Unmarshaler) unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *proto.Properties) error {
targetType := target.Type()
// Allocate memory for pointer fields.
if targetType.Kind() == reflect.Ptr {
target.Set(reflect.New(targetType.Elem()))
return unmarshalValue(target.Elem(), inputValue, prop)
return u.unmarshalValue(target.Elem(), inputValue, prop)
}
// Handle well-known types.
@ -559,7 +581,7 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *prot
// as the wrapped primitive type, except that null is allowed."
// encoding/json will turn JSON `null` into Go `nil`,
// so we don't have to do any extra work.
return unmarshalValue(target.Field(0), inputValue, prop)
return u.unmarshalValue(target.Field(0), inputValue, prop)
case "Any":
return fmt.Errorf("unmarshaling Any not supported yet")
case "Duration":
@ -657,7 +679,7 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *prot
continue
}
if err := unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil {
if err := u.unmarshalValue(target.Field(i), valueForField, sprops.Prop[i]); err != nil {
return err
}
}
@ -670,12 +692,12 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *prot
}
nv := reflect.New(oop.Type.Elem())
target.Field(oop.Field).Set(nv)
if err := unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil {
if err := u.unmarshalValue(nv.Elem().Field(0), raw, oop.Prop); err != nil {
return err
}
}
}
if len(jsonFields) > 0 {
if !u.AllowUnknownFields && len(jsonFields) > 0 {
// Pick any field to be the scapegoat.
var f string
for fname := range jsonFields {
@ -696,7 +718,7 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *prot
len := len(slc)
target.Set(reflect.MakeSlice(targetType, len, len))
for i := 0; i < len; i++ {
if err := unmarshalValue(target.Index(i), slc[i], prop); err != nil {
if err := u.unmarshalValue(target.Index(i), slc[i], prop); err != nil {
return err
}
}
@ -725,14 +747,14 @@ func unmarshalValue(target reflect.Value, inputValue json.RawMessage, prop *prot
k = reflect.ValueOf(ks)
} else {
k = reflect.New(targetType.Key()).Elem()
if err := unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil {
if err := u.unmarshalValue(k, json.RawMessage(ks), keyprop); err != nil {
return err
}
}
// Unmarshal map value.
v := reflect.New(targetType.Elem()).Elem()
if err := unmarshalValue(v, raw, valprop); err != nil {
if err := u.unmarshalValue(v, raw, valprop); err != nil {
return err
}
target.SetMapIndex(k, v)

View File

@ -36,6 +36,7 @@ import (
"encoding/json"
"io"
"reflect"
"strings"
"testing"
"github.com/golang/protobuf/proto"
@ -410,66 +411,69 @@ func TestMarshaling(t *testing.T) {
}
var unmarshalingTests = []struct {
desc string
json string
pb proto.Message
desc string
unmarshaler Unmarshaler
json string
pb proto.Message
}{
{"simple flat object", simpleObjectJSON, simpleObject},
{"simple pretty object", simpleObjectPrettyJSON, simpleObject},
{"repeated fields flat object", repeatsObjectJSON, repeatsObject},
{"repeated fields pretty object", repeatsObjectPrettyJSON, repeatsObject},
{"nested message/enum flat object", complexObjectJSON, complexObject},
{"nested message/enum pretty object", complexObjectPrettyJSON, complexObject},
{"enum-string object", `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
{"enum-value object", "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
{"proto3 enum string", `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"proto3 enum value", `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"simple flat object", Unmarshaler{}, simpleObjectJSON, simpleObject},
{"simple pretty object", Unmarshaler{}, simpleObjectPrettyJSON, simpleObject},
{"repeated fields flat object", Unmarshaler{}, repeatsObjectJSON, repeatsObject},
{"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject},
{"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject},
{"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject},
{"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
{"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
{"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)},
{"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
{"unknown enum value object",
Unmarshaler{},
"{\n \"color\": 1000,\n \"r_color\": [\n \"RED\"\n ]\n}",
&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}},
{"repeated proto3 enum", `{"rFunny":["PUNS","SLAPSTICK"]}`,
{"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
}}},
{"repeated proto3 enum as int", `{"rFunny":[1,2]}`,
{"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
}}},
{"repeated proto3 enum as mix of strings and ints", `{"rFunny":["PUNS",2]}`,
{"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`,
&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
proto3pb.Message_PUNS,
proto3pb.Message_SLAPSTICK,
}}},
{"unquoted int64 object", `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
{"unquoted uint64 object", `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
{"map<int64, int32>", `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
{"map<string, string>", `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
{"map<int32, Object>", `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}},
{"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
{"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
{"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
{"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
{"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: &pb.Simple3{Dub: 1}}}},
// TODO: This is broken.
//{"map<string, enum>", `{"enumy":{"XIV":"ROMAN"}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
{"map<string, enum as int>", `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
{"oneof", `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
{"oneof spec name", `{"country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
{"oneof orig_name", `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
{"orig_name input", `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"camelName input", `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
//{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
{"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
{"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
{"oneof spec name", Unmarshaler{}, `{"country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
{"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
{"Duration", `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
{"Timestamp", `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
{"DoubleValue", `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
{"FloatValue", `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
{"Int64Value", `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
{"UInt64Value", `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
{"Int32Value", `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
{"UInt32Value", `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
{"BoolValue", `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
{"StringValue", `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
{"BytesValue", `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
{"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
{"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
{"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
{"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
{"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
{"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
{"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
{"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
{"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
// `null` is also a permissible value. Let's just test one.
{"null DoubleValue", `{"dbl":null}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{}}},
{"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{}}},
}
func TestUnmarshaling(t *testing.T) {
@ -477,7 +481,7 @@ func TestUnmarshaling(t *testing.T) {
// Make a new instance of the type of our expected object.
p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
err := UnmarshalString(tt.json, p)
err := tt.unmarshaler.Unmarshal(strings.NewReader(tt.json), p)
if err != nil {
t.Errorf("%s: %v", tt.desc, err)
continue
@ -507,7 +511,7 @@ func TestUnmarshalNext(t *testing.T) {
// Make a new instance of the type of our expected object.
p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
err := UnmarshalNext(dec, p)
err := tt.unmarshaler.UnmarshalNext(dec, p)
if err != nil {
t.Errorf("%s: %v", tt.desc, err)
continue
@ -522,7 +526,7 @@ func TestUnmarshalNext(t *testing.T) {
}
p := &pb.Simple{}
err := UnmarshalNext(dec, p)
err := new(Unmarshaler).UnmarshalNext(dec, p)
if err != io.EOF {
t.Errorf("eof: got %v, expected io.EOF", err)
}
@ -535,6 +539,7 @@ var unmarshalingShouldError = []struct {
}{
{"a value", "666", new(pb.Simple)},
{"gibberish", "{adskja123;l23=-=", new(pb.Simple)},
{"unknown field", `{"unknown": "foo"}`, new(pb.Simple)},
{"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)},
}

View File

@ -195,6 +195,9 @@ var mergeTests = []struct {
NameMapping: map[int32]string{6: "Nigel"},
MsgMapping: map[int64]*pb.FloatingPoint{
0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
0x4002: &pb.FloatingPoint{
F: proto.Float64(2.0),
},
},
ByteMapping: map[bool][]byte{true: []byte("wowsa")},
},
@ -203,6 +206,12 @@ var mergeTests = []struct {
6: "Bruce", // should be overwritten
7: "Andrew",
},
MsgMapping: map[int64]*pb.FloatingPoint{
0x4002: &pb.FloatingPoint{
F: proto.Float64(3.0),
Exact: proto.Bool(true),
}, // the entire message should be overwritten
},
},
want: &pb.MessageWithMap{
NameMapping: map[int32]string{
@ -211,6 +220,9 @@ var mergeTests = []struct {
},
MsgMapping: map[int64]*pb.FloatingPoint{
0x4001: &pb.FloatingPoint{F: proto.Float64(2.0)},
0x4002: &pb.FloatingPoint{
F: proto.Float64(2.0),
},
},
ByteMapping: map[bool][]byte{true: []byte("wowsa")},
},
@ -254,6 +266,27 @@ var mergeTests = []struct {
Union: &pb.Communique_Name{"Bobby Tables"},
},
},
{
src: &proto3pb.Message{
Terrain: map[string]*proto3pb.Nested{
"kay_a": &proto3pb.Nested{Cute: true}, // replace
"kay_b": &proto3pb.Nested{Bunny: "rabbit"}, // insert
},
},
dst: &proto3pb.Message{
Terrain: map[string]*proto3pb.Nested{
"kay_a": &proto3pb.Nested{Bunny: "lost"}, // replaced
"kay_c": &proto3pb.Nested{Bunny: "bunny"}, // keep
},
},
want: &proto3pb.Message{
Terrain: map[string]*proto3pb.Nested{
"kay_a": &proto3pb.Nested{Cute: true},
"kay_b": &proto3pb.Nested{Bunny: "rabbit"},
"kay_c": &proto3pb.Nested{Bunny: "bunny"},
},
},
},
}
func TestMerge(t *testing.T) {

View File

@ -489,6 +489,34 @@ func GetExtensions(pb Message, es []*ExtensionDesc) (extensions []interface{}, e
return
}
// ExtensionDescs returns a new slice containing pb's extension descriptors, in undefined order.
// For non-registered extensions, ExtensionDescs returns an incomplete descriptor containing
// just the Field field, which defines the extension's field number.
func ExtensionDescs(pb Message) ([]*ExtensionDesc, error) {
epb, ok := extendable(pb)
if !ok {
return nil, fmt.Errorf("proto: %T is not an extendable proto.Message", pb)
}
registeredExtensions := RegisteredExtensions(pb)
emap, mu := epb.extensionsRead()
mu.Lock()
defer mu.Unlock()
extensions := make([]*ExtensionDesc, 0, len(emap))
for extid, e := range emap {
desc := e.desc
if desc == nil {
desc = registeredExtensions[extid]
if desc == nil {
desc = &ExtensionDesc{Field: extid}
}
}
extensions = append(extensions, desc)
}
return extensions, nil
}
// SetExtension sets the specified extension of pb to the specified value.
func SetExtension(pb Message, extension *ExtensionDesc, value interface{}) error {
epb, ok := extendable(pb)

View File

@ -35,6 +35,7 @@ import (
"bytes"
"fmt"
"reflect"
"sort"
"testing"
"github.com/golang/protobuf/proto"
@ -45,7 +46,7 @@ func TestGetExtensionsWithMissingExtensions(t *testing.T) {
msg := &pb.MyMessage{}
ext1 := &pb.Ext{}
if err := proto.SetExtension(msg, pb.E_Ext_More, ext1); err != nil {
t.Fatalf("Could not set ext1: %s", ext1)
t.Fatalf("Could not set ext1: %s", err)
}
exts, err := proto.GetExtensions(msg, []*proto.ExtensionDesc{
pb.E_Ext_More,
@ -62,6 +63,54 @@ func TestGetExtensionsWithMissingExtensions(t *testing.T) {
}
}
func TestExtensionDescsWithMissingExtensions(t *testing.T) {
msg := &pb.MyMessage{Count: proto.Int32(0)}
extdesc1 := pb.E_Ext_More
ext1 := &pb.Ext{}
if err := proto.SetExtension(msg, extdesc1, ext1); err != nil {
t.Fatalf("Could not set ext1: %s", err)
}
extdesc2 := &proto.ExtensionDesc{
ExtendedType: (*pb.MyMessage)(nil),
ExtensionType: (*bool)(nil),
Field: 123456789,
Name: "a.b",
Tag: "varint,123456789,opt",
}
ext2 := proto.Bool(false)
if err := proto.SetExtension(msg, extdesc2, ext2); err != nil {
t.Fatalf("Could not set ext2: %s", err)
}
b, err := proto.Marshal(msg)
if err != nil {
t.Fatalf("Could not marshal msg: %v", err)
}
if err := proto.Unmarshal(b, msg); err != nil {
t.Fatalf("Could not unmarshal into msg: %v", err)
}
descs, err := proto.ExtensionDescs(msg)
if err != nil {
t.Fatalf("proto.ExtensionDescs: got error %v", err)
}
sortExtDescs(descs)
wantDescs := []*proto.ExtensionDesc{extdesc1, &proto.ExtensionDesc{Field: extdesc2.Field}}
if !reflect.DeepEqual(descs, wantDescs) {
t.Errorf("proto.ExtensionDescs(msg) sorted extension ids: got %+v, want %+v", descs, wantDescs)
}
}
type ExtensionDescSlice []*proto.ExtensionDesc
func (s ExtensionDescSlice) Len() int { return len(s) }
func (s ExtensionDescSlice) Less(i, j int) bool { return s[i].Field < s[j].Field }
func (s ExtensionDescSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func sortExtDescs(s []*proto.ExtensionDesc) {
sort.Sort(ExtensionDescSlice(s))
}
func TestGetExtensionStability(t *testing.T) {
check := func(m *pb.MyMessage) bool {
ext1, err := proto.GetExtension(m, pb.E_Ext_More)

View File

@ -124,6 +124,7 @@ func (m *Message) GetManyThings() []*google_protobuf.Any {
type Nested struct {
Bunny string `protobuf:"bytes,1,opt,name=bunny" json:"bunny,omitempty"`
Cute bool `protobuf:"varint,2,opt,name=cute" json:"cute,omitempty"`
}
func (m *Nested) Reset() { *m = Nested{} }
@ -155,44 +156,44 @@ func init() {
}
var fileDescriptor0 = []byte{
// 617 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x92, 0x5d, 0x6b, 0xdb, 0x3c,
0x14, 0xc7, 0x1f, 0xc5, 0xa9, 0x93, 0x1e, 0x3b, 0xad, 0xd1, 0xd3, 0x81, 0x1a, 0xc6, 0xf0, 0x32,
0x18, 0x66, 0x2f, 0xee, 0xc8, 0x28, 0x94, 0x31, 0x36, 0xda, 0xae, 0x65, 0xa1, 0x69, 0x16, 0x9c,
0x76, 0x65, 0x57, 0x46, 0x49, 0x95, 0xc4, 0x2c, 0x96, 0x83, 0x2d, 0x0f, 0xfc, 0x75, 0xf6, 0x29,
0x77, 0x39, 0x24, 0x39, 0xa9, 0x5b, 0xb2, 0xed, 0xca, 0xd2, 0xf1, 0xef, 0xbc, 0xe8, 0xff, 0x3f,
0xb0, 0xbf, 0x4c, 0x13, 0x91, 0xbc, 0x0d, 0xd5, 0xe7, 0x40, 0x5f, 0x7c, 0xf5, 0xc1, 0x76, 0xf5,
0x57, 0x7b, 0x7f, 0x96, 0x24, 0xb3, 0x05, 0xd3, 0xc8, 0x38, 0x9f, 0x1e, 0x50, 0x5e, 0x68, 0xb0,
0xfd, 0xbf, 0x60, 0x99, 0xb8, 0xa5, 0x82, 0x1e, 0xc8, 0x83, 0x0e, 0x76, 0x7e, 0x99, 0xd0, 0xb8,
0x64, 0x59, 0x46, 0x67, 0x0c, 0x63, 0xa8, 0x73, 0x1a, 0x33, 0x82, 0x5c, 0xe4, 0x6d, 0x07, 0xea,
0x8c, 0x8f, 0xa0, 0x39, 0x8f, 0x16, 0x34, 0x8d, 0x44, 0x41, 0x6a, 0x2e, 0xf2, 0x76, 0xba, 0x8f,
0xfd, 0x6a, 0x43, 0xbf, 0x4c, 0xf6, 0x3f, 0xe7, 0x71, 0x92, 0xa7, 0xc1, 0x9a, 0xc6, 0x2e, 0xd8,
0x73, 0x16, 0xcd, 0xe6, 0x22, 0x8c, 0x78, 0x38, 0x89, 0x89, 0xe1, 0x22, 0xaf, 0x15, 0x80, 0x8e,
0xf5, 0xf8, 0x69, 0x2c, 0xfb, 0xc9, 0x71, 0x48, 0xdd, 0x45, 0x9e, 0x1d, 0xa8, 0x33, 0x7e, 0x0a,
0x76, 0xca, 0xb2, 0x7c, 0x21, 0xc2, 0x49, 0x92, 0x73, 0x41, 0x1a, 0x2e, 0xf2, 0x8c, 0xc0, 0xd2,
0xb1, 0x53, 0x19, 0xc2, 0xcf, 0xa0, 0x25, 0xd2, 0x9c, 0x85, 0xd9, 0x24, 0x11, 0x59, 0x4c, 0x39,
0x69, 0xba, 0xc8, 0x6b, 0x06, 0xb6, 0x0c, 0x8e, 0xca, 0x18, 0xde, 0x83, 0xad, 0x6c, 0x92, 0xa4,
0x8c, 0x6c, 0xbb, 0xc8, 0xab, 0x05, 0xfa, 0x82, 0x1d, 0x30, 0xbe, 0xb3, 0x82, 0x6c, 0xb9, 0x86,
0x57, 0x0f, 0xe4, 0x11, 0xbf, 0x02, 0x93, 0xb3, 0x4c, 0xb0, 0x5b, 0x62, 0xba, 0xc8, 0xb3, 0xba,
0x7b, 0xf7, 0x5f, 0x37, 0x50, 0xff, 0x82, 0x92, 0xc1, 0x87, 0xd0, 0x48, 0xc3, 0x69, 0xce, 0x79,
0x41, 0x1c, 0xd7, 0xf8, 0xa7, 0x18, 0x66, 0x7a, 0x2e, 0x59, 0xfc, 0x1e, 0x1a, 0x82, 0xa5, 0x29,
0x8d, 0x38, 0x01, 0xd7, 0xf0, 0xac, 0x6e, 0x67, 0x73, 0xda, 0x95, 0x86, 0xce, 0xb8, 0x48, 0x8b,
0x60, 0x95, 0x82, 0x8f, 0x40, 0x5b, 0xdc, 0x0d, 0xa7, 0x11, 0x5b, 0xdc, 0x12, 0x4b, 0x0d, 0xfa,
0xc8, 0x5f, 0xd9, 0xe9, 0x8f, 0xf2, 0xf1, 0x27, 0x36, 0xa5, 0xf9, 0x42, 0x64, 0x81, 0xa5, 0xd1,
0x73, 0x49, 0xe2, 0xde, 0x3a, 0xf3, 0x07, 0x5d, 0xe4, 0x8c, 0xb4, 0x54, 0xf3, 0xe7, 0x9b, 0x9b,
0x0f, 0x15, 0xf9, 0x55, 0x82, 0x7a, 0x80, 0xb2, 0x94, 0x8a, 0xe0, 0x37, 0xd0, 0xa4, 0xbc, 0x10,
0xf3, 0x88, 0xcf, 0xc8, 0x4e, 0xa9, 0x94, 0x5e, 0x35, 0x7f, 0xb5, 0x6a, 0xfe, 0x31, 0x2f, 0x82,
0x35, 0x85, 0x0f, 0xc1, 0x8a, 0x29, 0x2f, 0x42, 0x75, 0xcb, 0xc8, 0xae, 0xea, 0xbd, 0x39, 0x09,
0x24, 0x78, 0xa5, 0xb8, 0xf6, 0x10, 0xec, 0xaa, 0x0c, 0x2b, 0xcb, 0xf4, 0x4e, 0x2a, 0xcb, 0x5e,
0xc0, 0x96, 0x7e, 0x4e, 0xed, 0x2f, 0x8e, 0x69, 0xe4, 0x5d, 0xed, 0x08, 0xb5, 0xaf, 0xc1, 0x79,
0xf8, 0xb6, 0x0d, 0x55, 0x5f, 0xde, 0xaf, 0xfa, 0x07, 0x79, 0xef, 0xca, 0x76, 0x3e, 0x82, 0xa9,
0x6d, 0xc6, 0x16, 0x34, 0xae, 0x07, 0x17, 0x83, 0x2f, 0x37, 0x03, 0xe7, 0x3f, 0xdc, 0x84, 0xfa,
0xf0, 0x7a, 0x30, 0x72, 0x10, 0x6e, 0xc1, 0xf6, 0xa8, 0x7f, 0x3c, 0x1c, 0x5d, 0xf5, 0x4e, 0x2f,
0x9c, 0x1a, 0xde, 0x05, 0xeb, 0xa4, 0xd7, 0xef, 0x87, 0x27, 0xc7, 0xbd, 0xfe, 0xd9, 0x37, 0xc7,
0xe8, 0x3c, 0x01, 0x53, 0x0f, 0x2b, 0x97, 0x75, 0xac, 0x96, 0x4a, 0xcf, 0xa3, 0x2f, 0x9d, 0x9f,
0x08, 0x76, 0x4a, 0x73, 0x6e, 0x22, 0x31, 0xbf, 0xa4, 0x4b, 0x3c, 0x04, 0x7b, 0x5c, 0x08, 0x16,
0xc6, 0x74, 0xb9, 0x94, 0x4e, 0x20, 0x25, 0xea, 0xeb, 0x8d, 0x86, 0x96, 0x39, 0xfe, 0x49, 0x21,
0xd8, 0xa5, 0xe6, 0x4b, 0x5f, 0xc7, 0x77, 0x91, 0xf6, 0x07, 0x70, 0x1e, 0x02, 0x55, 0x71, 0x9a,
0x5a, 0x9c, 0xbd, 0xaa, 0x38, 0x76, 0x45, 0x85, 0xb1, 0xa9, 0x5b, 0xff, 0x0e, 0x00, 0x00, 0xff,
0xff, 0x54, 0x4a, 0xfa, 0x41, 0xa1, 0x04, 0x00, 0x00,
// 621 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x53, 0x5b, 0x6f, 0xd3, 0x4c,
0x10, 0xfd, 0x72, 0xa9, 0xe3, 0x8e, 0x9d, 0xd6, 0xda, 0xaf, 0x48, 0xdb, 0x88, 0x87, 0x12, 0x24,
0x54, 0x71, 0x71, 0x51, 0x10, 0x52, 0x85, 0x10, 0xa8, 0x2d, 0xad, 0x88, 0x9a, 0x86, 0x68, 0xd3,
0x52, 0xf1, 0x64, 0xad, 0xd3, 0x4d, 0x62, 0x11, 0xaf, 0x23, 0x7b, 0x8d, 0xe4, 0xbf, 0xc3, 0xaf,
0xe4, 0x91, 0xbd, 0x38, 0xad, 0x5b, 0x05, 0x78, 0xf2, 0xee, 0xcc, 0x39, 0x33, 0xb3, 0xe7, 0x8c,
0x61, 0x77, 0x99, 0x26, 0x22, 0x79, 0x13, 0xe8, 0xcf, 0x81, 0xb9, 0xf8, 0xfa, 0x83, 0xdc, 0x6a,
0xaa, 0xb3, 0x3b, 0x4b, 0x92, 0xd9, 0x82, 0x19, 0x48, 0x98, 0x4f, 0x0f, 0x28, 0x2f, 0x0c, 0xb0,
0xf3, 0xbf, 0x60, 0x99, 0xb8, 0xa1, 0x82, 0x1e, 0xa8, 0x83, 0x09, 0x76, 0x7f, 0x59, 0xd0, 0xba,
0x60, 0x59, 0x46, 0x67, 0x0c, 0x21, 0x68, 0x72, 0x1a, 0x33, 0x5c, 0xdb, 0xab, 0xed, 0x6f, 0x12,
0x7d, 0x46, 0x87, 0x60, 0xcf, 0xa3, 0x05, 0x4d, 0x23, 0x51, 0xe0, 0xba, 0x8c, 0x6f, 0xf5, 0x1e,
0xfb, 0xd5, 0x86, 0x7e, 0x49, 0xf6, 0x3f, 0xe7, 0x71, 0x92, 0xa7, 0xe4, 0x16, 0x8d, 0xf6, 0xc0,
0x9d, 0xb3, 0x68, 0x36, 0x17, 0x41, 0xc4, 0x83, 0x49, 0x8c, 0x1b, 0x92, 0xdd, 0x26, 0x60, 0x62,
0x7d, 0x7e, 0x12, 0xab, 0x7e, 0x6a, 0x1c, 0xdc, 0x94, 0x19, 0x97, 0xe8, 0x33, 0x7a, 0x02, 0x6e,
0xca, 0xb2, 0x7c, 0x21, 0x82, 0x49, 0x92, 0x73, 0x81, 0x5b, 0x32, 0xd7, 0x20, 0x8e, 0x89, 0x9d,
0xa8, 0x10, 0x7a, 0x0a, 0x6d, 0x91, 0xe6, 0x2c, 0xc8, 0x26, 0x89, 0xc8, 0x62, 0xca, 0xb1, 0x2d,
0x31, 0x36, 0x71, 0x55, 0x70, 0x5c, 0xc6, 0xd0, 0x0e, 0x6c, 0xc8, 0x7c, 0xca, 0xf0, 0xa6, 0x4c,
0xd6, 0x89, 0xb9, 0x20, 0x0f, 0x1a, 0xdf, 0x59, 0x81, 0x37, 0xf6, 0x1a, 0xfb, 0x4d, 0xa2, 0x8e,
0xe8, 0x25, 0x58, 0x5c, 0xaa, 0xc1, 0x6e, 0xb0, 0x25, 0x81, 0x4e, 0x6f, 0xe7, 0xfe, 0xeb, 0x86,
0x3a, 0x47, 0x4a, 0x0c, 0x7a, 0x0b, 0xad, 0x34, 0x98, 0xe6, 0x9c, 0x17, 0xd8, 0x93, 0x35, 0xfe,
0x25, 0x86, 0x95, 0x9e, 0x29, 0x2c, 0x7a, 0x0f, 0x2d, 0xc1, 0xd2, 0x94, 0x46, 0x1c, 0x83, 0xa4,
0x39, 0xbd, 0xee, 0x7a, 0xda, 0xa5, 0x01, 0x9d, 0x72, 0x91, 0x16, 0x64, 0x45, 0x91, 0x16, 0x18,
0x8b, 0x7b, 0xc1, 0x34, 0x62, 0x8b, 0x1b, 0xec, 0xe8, 0x41, 0x1f, 0xf9, 0x2b, 0x3b, 0xfd, 0x71,
0x1e, 0x7e, 0x62, 0x53, 0x2a, 0x05, 0xca, 0x88, 0x63, 0xa0, 0x67, 0x0a, 0x89, 0xfa, 0xb7, 0xcc,
0x1f, 0x74, 0x91, 0x33, 0xdc, 0xd6, 0xcd, 0x9f, 0xad, 0x6f, 0x3e, 0xd2, 0xc8, 0xaf, 0x0a, 0x68,
0x06, 0x28, 0x4b, 0xe9, 0x08, 0x7a, 0x0d, 0xb6, 0xdc, 0x24, 0x31, 0x8f, 0xf8, 0x0c, 0x6f, 0x95,
0x4a, 0x99, 0x55, 0xf3, 0x57, 0xab, 0xe6, 0x1f, 0xf1, 0x82, 0xdc, 0xa2, 0xa4, 0x56, 0x8e, 0x34,
0xa2, 0x08, 0xf4, 0x2d, 0xc3, 0xdb, 0xba, 0xf7, 0x7a, 0x12, 0x28, 0xe0, 0xa5, 0xc6, 0x75, 0x46,
0xe0, 0x56, 0x65, 0x58, 0x59, 0x66, 0x76, 0x52, 0x5b, 0xf6, 0x1c, 0x36, 0xcc, 0x73, 0xea, 0x7f,
0x71, 0xcc, 0x40, 0xde, 0xd5, 0x0f, 0x6b, 0x9d, 0x2b, 0xf0, 0x1e, 0xbe, 0x6d, 0x4d, 0xd5, 0x17,
0xf7, 0xab, 0xfe, 0x41, 0xde, 0xbb, 0xb2, 0xdd, 0x8f, 0x60, 0x19, 0x9b, 0x91, 0x03, 0xad, 0xab,
0xe1, 0xf9, 0xf0, 0xcb, 0xf5, 0xd0, 0xfb, 0x0f, 0xd9, 0xd0, 0x1c, 0x5d, 0x0d, 0xc7, 0x5e, 0x0d,
0xb5, 0x61, 0x73, 0x3c, 0x38, 0x1a, 0x8d, 0x2f, 0xfb, 0x27, 0xe7, 0x5e, 0x1d, 0x6d, 0x83, 0x73,
0xdc, 0x1f, 0x0c, 0x82, 0xe3, 0xa3, 0xfe, 0xe0, 0xf4, 0x9b, 0xd7, 0xe8, 0xf6, 0xc0, 0x32, 0xc3,
0xaa, 0x65, 0x0d, 0xf5, 0x52, 0x99, 0x79, 0xcc, 0x45, 0xfd, 0x1e, 0x93, 0x5c, 0x98, 0x81, 0x6c,
0xa2, 0xcf, 0xdd, 0x9f, 0x35, 0xd8, 0x2a, 0x0d, 0xbb, 0x8e, 0xc4, 0xfc, 0x82, 0x2e, 0x91, 0x14,
0x2c, 0x2c, 0x04, 0x0b, 0x62, 0xba, 0x5c, 0x2a, 0x77, 0x6a, 0x5a, 0xe8, 0x57, 0x6b, 0x4d, 0x2e,
0x39, 0xfe, 0xb1, 0x24, 0x5c, 0x18, 0x7c, 0xe9, 0x75, 0x78, 0x17, 0xe9, 0x7c, 0x00, 0xef, 0x21,
0xa0, 0x2a, 0x98, 0x6d, 0x04, 0xdb, 0xa9, 0x0a, 0xe6, 0x56, 0x94, 0x09, 0x2d, 0xd3, 0xfa, 0x77,
0x00, 0x00, 0x00, 0xff, 0xff, 0x78, 0xc9, 0x75, 0x36, 0xb5, 0x04, 0x00, 0x00,
}

View File

@ -66,6 +66,7 @@ message Message {
message Nested {
string bunny = 1;
bool cute = 2;
}
message MessageWithMap {

View File

@ -53,9 +53,7 @@ var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
const _ = proto.ProtoPackageIsVersion1
type FOO int32
@ -1268,12 +1266,12 @@ func (m *InnerMessage) GetConnected() bool {
}
type OtherMessage struct {
Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"`
Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"`
Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
Key *int64 `protobuf:"varint,1,opt,name=key" json:"key,omitempty"`
Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
Weight *float32 `protobuf:"fixed32,3,opt,name=weight" json:"weight,omitempty"`
Inner *InnerMessage `protobuf:"bytes,4,opt,name=inner" json:"inner,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *OtherMessage) Reset() { *m = OtherMessage{} }
@ -1288,6 +1286,12 @@ var extRange_OtherMessage = []proto.ExtensionRange{
func (*OtherMessage) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_OtherMessage
}
func (m *OtherMessage) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
func (m *OtherMessage) GetKey() int64 {
if m != nil && m.Key != nil {
@ -1346,10 +1350,10 @@ type MyMessage struct {
Bikeshed *MyMessage_Color `protobuf:"varint,7,opt,name=bikeshed,enum=testdata.MyMessage_Color" json:"bikeshed,omitempty"`
Somegroup *MyMessage_SomeGroup `protobuf:"group,8,opt,name=SomeGroup,json=somegroup" json:"somegroup,omitempty"`
// This field becomes [][]byte in the generated code.
RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes,json=repBytes" json:"rep_bytes,omitempty"`
Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
RepBytes [][]byte `protobuf:"bytes,10,rep,name=rep_bytes,json=repBytes" json:"rep_bytes,omitempty"`
Bigfloat *float64 `protobuf:"fixed64,11,opt,name=bigfloat" json:"bigfloat,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *MyMessage) Reset() { *m = MyMessage{} }
@ -1364,6 +1368,12 @@ var extRange_MyMessage = []proto.ExtensionRange{
func (*MyMessage) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_MyMessage
}
func (m *MyMessage) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
func (m *MyMessage) GetCount() int32 {
if m != nil && m.Count != nil {
@ -1541,8 +1551,8 @@ func (m *ComplexExtension) GetThird() []int32 {
}
type DefaultsMessage struct {
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *DefaultsMessage) Reset() { *m = DefaultsMessage{} }
@ -1557,10 +1567,16 @@ var extRange_DefaultsMessage = []proto.ExtensionRange{
func (*DefaultsMessage) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_DefaultsMessage
}
func (m *DefaultsMessage) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
type MyMessageSet struct {
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *MyMessageSet) Reset() { *m = MyMessageSet{} }
@ -1569,16 +1585,16 @@ func (*MyMessageSet) ProtoMessage() {}
func (*MyMessageSet) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
func (m *MyMessageSet) Marshal() ([]byte, error) {
return proto.MarshalMessageSet(&m.XXX_InternalExtensions)
return proto.MarshalMessageSet(m.ExtensionMap())
}
func (m *MyMessageSet) Unmarshal(buf []byte) error {
return proto.UnmarshalMessageSet(buf, &m.XXX_InternalExtensions)
return proto.UnmarshalMessageSet(buf, m.ExtensionMap())
}
func (m *MyMessageSet) MarshalJSON() ([]byte, error) {
return proto.MarshalMessageSetJSON(&m.XXX_InternalExtensions)
return proto.MarshalMessageSetJSON(m.XXX_extensions)
}
func (m *MyMessageSet) UnmarshalJSON(buf []byte) error {
return proto.UnmarshalMessageSetJSON(buf, &m.XXX_InternalExtensions)
return proto.UnmarshalMessageSetJSON(buf, m.XXX_extensions)
}
// ensure MyMessageSet satisfies proto.Marshaler and proto.Unmarshaler
@ -1592,6 +1608,12 @@ var extRange_MyMessageSet = []proto.ExtensionRange{
func (*MyMessageSet) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_MyMessageSet
}
func (m *MyMessageSet) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
type Empty struct {
XXX_unrecognized []byte `json:"-"`
@ -2035,6 +2057,7 @@ func (m *GroupNew_G) GetY() int32 {
type FloatingPoint struct {
F *float64 `protobuf:"fixed64,1,req,name=f" json:"f,omitempty"`
Exact *bool `protobuf:"varint,2,opt,name=exact" json:"exact,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
@ -2050,6 +2073,13 @@ func (m *FloatingPoint) GetF() float64 {
return 0
}
func (m *FloatingPoint) GetExact() bool {
if m != nil && m.Exact != nil {
return *m.Exact
}
return false
}
type MessageWithMap struct {
NameMapping map[int32]string `protobuf:"bytes,1,rep,name=name_mapping,json=nameMapping" json:"name_mapping,omitempty" protobuf_key:"varint,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
MsgMapping map[int64]*FloatingPoint `protobuf:"bytes,2,rep,name=msg_mapping,json=msgMapping" json:"msg_mapping,omitempty" protobuf_key:"zigzag64,1,opt,name=key" protobuf_val:"bytes,2,opt,name=value"`
@ -3726,41 +3756,39 @@ func init() {
proto.RegisterExtension(E_X250)
}
func init() { proto.RegisterFile("test.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 4335 bytes of a gzipped FileDescriptorProto
// 4349 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x94, 0x5a, 0x4b, 0x77, 0x1b, 0x47,
0x76, 0x76, 0xe3, 0x8d, 0x02, 0x48, 0x80, 0x2d, 0x59, 0x82, 0xa8, 0x87, 0x65, 0xcc, 0xd8, 0x96,
0x64, 0x9b, 0x43, 0x34, 0x40, 0x52, 0x82, 0x27, 0x73, 0x8e, 0x28, 0x91, 0x1c, 0x9e, 0x11, 0x09,
0xa6, 0x49, 0xdb, 0x67, 0x9c, 0x05, 0x0e, 0x28, 0x36, 0x40, 0x58, 0x00, 0x1a, 0x02, 0xc0, 0x48,
0x64, 0x9b, 0x23, 0x34, 0x40, 0x52, 0x82, 0x27, 0x73, 0x8e, 0x28, 0x91, 0x1c, 0x9e, 0x11, 0x09,
0xa6, 0x49, 0xdb, 0x67, 0x9c, 0x05, 0x0e, 0x48, 0x36, 0x40, 0x58, 0x00, 0x1a, 0x02, 0xc0, 0x48,
0x4c, 0x36, 0xd9, 0x24, 0xdb, 0xbc, 0x36, 0xd9, 0x66, 0x95, 0x55, 0x92, 0x73, 0xf2, 0x27, 0x12,
0xdb, 0xf3, 0xf4, 0x3c, 0xf3, 0x9c, 0xbc, 0x1f, 0x93, 0xf7, 0x6b, 0x26, 0xc9, 0x26, 0x73, 0xef,
0xad, 0xdb, 0xdd, 0xd5, 0x0d, 0x74, 0x93, 0xd2, 0xc2, 0x44, 0x57, 0x7d, 0xdf, 0xad, 0x5b, 0xd5,
0x5f, 0xdd, 0x5b, 0xb7, 0xda, 0x42, 0x4c, 0xac, 0xf1, 0x64, 0x69, 0x38, 0xb2, 0x27, 0xb6, 0x9e,
0xc1, 0xdf, 0x47, 0xad, 0x49, 0xab, 0x7c, 0x5b, 0xa4, 0xb6, 0xec, 0x8d, 0xc1, 0x49, 0x5f, 0x7f,
0xc1, 0xdf, 0x47, 0xad, 0x49, 0xab, 0x7c, 0x5b, 0xa4, 0x36, 0xed, 0xf5, 0xc1, 0x49, 0x5f, 0x7f,
0x45, 0xc4, 0xdb, 0xb6, 0x5d, 0xd2, 0x6e, 0xc6, 0x6e, 0xcd, 0x1b, 0x73, 0x4b, 0x0e, 0x62, 0x69,
0xb3, 0xd1, 0x30, 0xb1, 0xa7, 0xbc, 0x26, 0x72, 0x5b, 0xf6, 0x01, 0x34, 0x6f, 0x76, 0xad, 0xde,
0x91, 0x7e, 0x51, 0x24, 0x1f, 0xb5, 0x0e, 0xad, 0x1e, 0x31, 0xb2, 0x66, 0xb2, 0x87, 0x0f, 0xba,
0x2e, 0x12, 0x07, 0xa7, 0x43, 0xab, 0x14, 0xa3, 0xc6, 0xc4, 0x04, 0x7e, 0x97, 0x7f, 0xf9, 0x06,
0xa3, 0xd1, 0x30, 0xb1, 0xa7, 0xbc, 0x2a, 0x72, 0x9b, 0xf6, 0x3e, 0x34, 0x6f, 0x74, 0xad, 0xde,
0x91, 0x7e, 0x51, 0x24, 0x1f, 0xb7, 0x0e, 0xac, 0x1e, 0x31, 0xb2, 0x66, 0xb2, 0x87, 0x0f, 0xba,
0x2e, 0x12, 0xfb, 0xa7, 0x43, 0xab, 0x14, 0xa3, 0xc6, 0xc4, 0x04, 0x7e, 0x97, 0x7f, 0xf9, 0x06,
0x0e, 0x82, 0x4c, 0xfd, 0xb6, 0x48, 0x7c, 0xa9, 0x3b, 0x38, 0xe2, 0x51, 0x5e, 0xf6, 0x46, 0x91,
0xfd, 0x4b, 0x5f, 0xda, 0xde, 0x7d, 0x68, 0x26, 0x9e, 0x00, 0x04, 0xed, 0x1f, 0xb4, 0x0e, 0x7b,
0x68, 0x4a, 0x43, 0xfb, 0x13, 0x7c, 0xc0, 0xd6, 0xbd, 0xd6, 0xa8, 0xd5, 0x2f, 0xc5, 0xa1, 0x35,
0xfd, 0x4b, 0x5f, 0xda, 0xda, 0x79, 0x64, 0x26, 0x9e, 0x00, 0x04, 0xed, 0xef, 0xb7, 0x0e, 0x7a,
0x68, 0x4a, 0x43, 0xfb, 0x13, 0x7c, 0xc0, 0xd6, 0xdd, 0xd6, 0xa8, 0xd5, 0x2f, 0xc5, 0xa1, 0x35,
0x69, 0x26, 0x87, 0xf8, 0xa0, 0xbf, 0x23, 0xe6, 0x4c, 0xeb, 0xe9, 0x49, 0x77, 0x64, 0x1d, 0x91,
0x73, 0xa5, 0x04, 0xd8, 0xcf, 0x4d, 0xdb, 0xa7, 0x4e, 0x73, 0x6e, 0xa4, 0x62, 0x25, 0x79, 0x68,
0xb5, 0x26, 0x0e, 0x39, 0x79, 0x33, 0x1e, 0x49, 0x56, 0xb0, 0x48, 0x6e, 0x0c, 0x27, 0x5d, 0x7b,
0xd0, 0xea, 0x49, 0x72, 0x0a, 0xfc, 0x0a, 0x27, 0xdb, 0x2a, 0x56, 0x7f, 0x5d, 0x14, 0x36, 0x9b,
0xeb, 0xb6, 0xdd, 0x6b, 0x3a, 0x1e, 0x95, 0x04, 0x38, 0x9e, 0x31, 0xe7, 0xda, 0xd8, 0xea, 0x4c,
0x49, 0xbf, 0x25, 0x8a, 0x9b, 0xcd, 0xed, 0xc1, 0xa4, 0x6a, 0x78, 0xc0, 0x1c, 0x00, 0x93, 0xe6,
0x7c, 0x9b, 0x9a, 0xa7, 0x90, 0xab, 0x35, 0x0f, 0x99, 0x07, 0x64, 0x5c, 0x22, 0x57, 0x6b, 0x2e,
0xf2, 0x2d, 0xa1, 0x6f, 0x36, 0x37, 0xbb, 0xcf, 0xad, 0x23, 0xd5, 0xea, 0x1c, 0x60, 0xd3, 0x66,
0xd0, 0xea, 0x49, 0x72, 0x0a, 0xfc, 0x0a, 0x27, 0xdb, 0x2a, 0x56, 0x7f, 0x5d, 0x14, 0x36, 0x9a,
0x6b, 0xb6, 0xdd, 0x6b, 0x3a, 0x1e, 0x95, 0x04, 0x38, 0x9e, 0x31, 0xe7, 0xda, 0xd8, 0xea, 0x4c,
0x49, 0xbf, 0x25, 0x8a, 0x1b, 0xcd, 0xad, 0xc1, 0xa4, 0x6a, 0x78, 0xc0, 0x1c, 0x00, 0x93, 0xe6,
0x7c, 0x9b, 0x9a, 0xa7, 0x90, 0x2b, 0x35, 0x0f, 0x99, 0x07, 0x64, 0x5c, 0x22, 0x57, 0x6a, 0x2e,
0xf2, 0x2d, 0xa1, 0x6f, 0x34, 0x37, 0xba, 0xcf, 0xad, 0x23, 0xd5, 0xea, 0x1c, 0x60, 0xd3, 0x66,
0xb1, 0xcd, 0x1d, 0x33, 0xd0, 0xaa, 0xe5, 0x79, 0x40, 0xa7, 0x1c, 0xb4, 0x62, 0xfb, 0x8e, 0x58,
0xd8, 0x6c, 0xbe, 0xdb, 0xf5, 0x3b, 0x5c, 0x00, 0xf0, 0x9c, 0x59, 0x68, 0xcb, 0xf6, 0x69, 0xac,
0x6a, 0xb8, 0x08, 0xd8, 0x04, 0x63, 0x15, 0xbb, 0x34, 0xbb, 0xcd, 0x9e, 0xdd, 0x9a, 0x78, 0xd0,
0x05, 0x80, 0xc6, 0x60, 0x76, 0xd4, 0xec, 0xb7, 0xfa, 0xd0, 0x3e, 0x01, 0xc9, 0x78, 0x50, 0x1d,
0xa0, 0x1a, 0x58, 0x95, 0xed, 0x7e, 0xec, 0xfe, 0x64, 0xd4, 0x1d, 0x74, 0x3c, 0xec, 0x05, 0xd2,
0x6f, 0xa1, 0x2d, 0xdb, 0xfd, 0x1e, 0xac, 0x9f, 0xc2, 0xcb, 0xf5, 0xa0, 0x16, 0x40, 0xf3, 0xe0,
0x01, 0x35, 0x07, 0xac, 0x06, 0xd6, 0xa0, 0x0d, 0xd0, 0x05, 0xb4, 0x3a, 0x63, 0x0d, 0xf6, 0x03,
0xd8, 0x68, 0xbe, 0xdb, 0xf5, 0x3b, 0x5c, 0x00, 0xf0, 0x9c, 0x59, 0x68, 0xcb, 0xf6, 0x69, 0xac,
0x6a, 0xb8, 0x08, 0xd8, 0x04, 0x63, 0x15, 0xbb, 0x34, 0xbb, 0x8d, 0x9e, 0xdd, 0x9a, 0x78, 0xd0,
0x05, 0x80, 0xc6, 0x60, 0x76, 0xd4, 0xec, 0xb7, 0xfa, 0xc8, 0x3e, 0x01, 0xc9, 0x78, 0x50, 0x1d,
0xa0, 0x1a, 0x58, 0x95, 0xed, 0x7e, 0xec, 0xde, 0x64, 0xd4, 0x1d, 0x74, 0x3c, 0xec, 0x05, 0xd2,
0x6f, 0xa1, 0x2d, 0xdb, 0xfd, 0x1e, 0xac, 0x9d, 0xc2, 0xcb, 0xf5, 0xa0, 0x16, 0x40, 0xf3, 0xe0,
0x01, 0x35, 0x07, 0xac, 0x06, 0xd6, 0xa0, 0x0d, 0xd0, 0x05, 0xb4, 0x3a, 0x63, 0x0d, 0xf6, 0x02,
0x6b, 0xd0, 0x01, 0xac, 0xce, 0x58, 0x65, 0x0d, 0x54, 0xcd, 0x48, 0x21, 0x96, 0x2e, 0x82, 0x5e,
0x3d, 0xcd, 0xc8, 0x46, 0xbf, 0x66, 0x18, 0xf8, 0x32, 0x00, 0x15, 0xcd, 0x04, 0x90, 0x34, 0x38,
0x23, 0x2f, 0x01, 0x52, 0xd1, 0x0c, 0x23, 0x03, 0x9a, 0x61, 0xec, 0x65, 0xc0, 0xfa, 0x34, 0x33,
@ -3779,226 +3807,227 @@ var fileDescriptor0 = []byte{
0x1b, 0x17, 0xfa, 0xdb, 0x98, 0x0b, 0x5d, 0xd9, 0xb8, 0x50, 0x55, 0x36, 0x2e, 0xf6, 0x77, 0x10,
0xeb, 0xc9, 0x66, 0x1a, 0xac, 0xae, 0xc2, 0xef, 0x22, 0xd8, 0x93, 0x8d, 0x0b, 0x5e, 0x22, 0x27,
0x50, 0x36, 0x47, 0x56, 0xbb, 0x75, 0xd2, 0x43, 0x89, 0xdd, 0x42, 0xdd, 0xd4, 0x13, 0x93, 0xd1,
0x89, 0x85, 0x9e, 0x40, 0xe7, 0x43, 0xa7, 0x0f, 0xf0, 0x0b, 0x8e, 0x7c, 0x3c, 0xc2, 0x6d, 0xd4,
0x89, 0x85, 0x9e, 0x40, 0xe7, 0x23, 0xa7, 0x0f, 0xf0, 0x0b, 0x8e, 0x7c, 0x3c, 0xc2, 0x6d, 0xd4,
0x4f, 0x3d, 0x06, 0xd2, 0x2d, 0x48, 0x0d, 0x4d, 0xe3, 0xc1, 0x17, 0x0f, 0x7f, 0x07, 0x55, 0x54,
0x8f, 0x81, 0x7a, 0x0b, 0x52, 0x49, 0x1e, 0xbe, 0x2a, 0x2e, 0x78, 0x52, 0xf2, 0x18, 0x6f, 0xa2,
0x96, 0xea, 0xf1, 0xaa, 0xb1, 0x6c, 0x2e, 0x38, 0x82, 0x9a, 0x45, 0xf2, 0x0d, 0xf3, 0x16, 0x4a,
0xaa, 0x1e, 0x5f, 0xad, 0xb9, 0x24, 0x75, 0x24, 0x03, 0x65, 0xc8, 0xc2, 0xf2, 0x38, 0x6f, 0xa3,
0xb2, 0xea, 0x09, 0x18, 0x68, 0x19, 0xc4, 0x28, 0xbb, 0x67, 0x70, 0x7c, 0xe3, 0x2c, 0xa1, 0xc2,
0xea, 0x09, 0x18, 0xc7, 0xe1, 0xf8, 0xc7, 0x59, 0x70, 0x84, 0xe6, 0x51, 0x3e, 0x87, 0x4a, 0xab,
0xa7, 0xaa, 0x95, 0x5a, 0x65, 0xe5, 0x1e, 0xac, 0x02, 0xf5, 0x7b, 0x9c, 0x1a, 0x8e, 0xc3, 0x92,
0xf3, 0x48, 0xcb, 0xa8, 0xb9, 0x7a, 0xca, 0x58, 0xab, 0xdc, 0x35, 0xee, 0xc2, 0x48, 0x12, 0xe0,
0xb1, 0xbe, 0x80, 0x2c, 0x16, 0x9f, 0xc7, 0xaa, 0xa0, 0xfa, 0xea, 0xc5, 0x63, 0xab, 0xd7, 0xb3,
0xdf, 0xba, 0x59, 0x7e, 0x66, 0x8f, 0x7a, 0x47, 0xaf, 0x96, 0x05, 0xf0, 0x25, 0x54, 0x1d, 0x75,
0xc1, 0x11, 0xa4, 0x47, 0xff, 0x55, 0x3c, 0x87, 0xe5, 0xeb, 0xe9, 0xf5, 0x6e, 0x67, 0x60, 0x8f,
0x2d, 0xf0, 0x95, 0x10, 0x81, 0x35, 0xd9, 0x0f, 0xae, 0xe3, 0xaf, 0x21, 0x6d, 0xa1, 0x1e, 0x7f,
0x1b, 0x44, 0x51, 0x64, 0x85, 0xce, 0xe0, 0xf8, 0xd6, 0xf1, 0xd7, 0x91, 0xa3, 0x03, 0x07, 0x84,
0x51, 0x64, 0xa1, 0x7a, 0x9c, 0x35, 0x71, 0x29, 0x90, 0x17, 0x9b, 0xc3, 0xd6, 0xe3, 0x27, 0xc0,
0x33, 0x30, 0x3d, 0xae, 0xc7, 0x8a, 0x9a, 0x79, 0xc1, 0x97, 0x22, 0xf7, 0xa8, 0x5b, 0xbf, 0x27,
0x2e, 0x07, 0x13, 0xa5, 0xc3, 0xac, 0x62, 0xbe, 0x24, 0xe6, 0x45, 0x7f, 0xce, 0x0c, 0x50, 0x95,
0x00, 0xec, 0x50, 0x6b, 0x98, 0x40, 0x3d, 0xaa, 0x17, 0x89, 0x99, 0xfa, 0x53, 0xe2, 0xca, 0x74,
0x2a, 0x75, 0xc8, 0x2b, 0x98, 0x51, 0x89, 0x7c, 0x29, 0x98, 0x55, 0xa7, 0xe8, 0x33, 0xc6, 0x5e,
0xc5, 0x14, 0xab, 0xd2, 0xa7, 0x46, 0x7f, 0x47, 0x94, 0xa6, 0x92, 0xad, 0xc3, 0x5e, 0xc3, 0x9c,
0x4b, 0xec, 0x97, 0x03, 0x79, 0x37, 0x48, 0x9e, 0x31, 0xf4, 0x5d, 0x4c, 0xc2, 0x0a, 0x79, 0x6a,
0x64, 0x5a, 0x32, 0x7f, 0x3a, 0x76, 0xb8, 0xf7, 0x30, 0x2b, 0xf3, 0x92, 0xf9, 0x32, 0xb3, 0x3a,
0x6e, 0x20, 0x3f, 0x3b, 0xdc, 0x3a, 0xa6, 0x69, 0x1e, 0xd7, 0x9f, 0xaa, 0x99, 0xfc, 0x79, 0x24,
0xef, 0xcf, 0x9e, 0xf1, 0x8f, 0xe2, 0x98, 0x60, 0x99, 0xbd, 0x3f, 0x6b, 0xca, 0x2e, 0x7b, 0xc6,
0x94, 0x7f, 0x8c, 0x6c, 0x5d, 0x61, 0x4f, 0xcd, 0xf9, 0xa1, 0x70, 0x2b, 0x8e, 0xce, 0xc8, 0x3e,
0x19, 0x96, 0x36, 0xe1, 0x68, 0x27, 0x8c, 0x1b, 0x53, 0xd5, 0x8f, 0x73, 0xc8, 0xdb, 0x42, 0x94,
0xe9, 0x27, 0x49, 0x2b, 0xd2, 0xae, 0xb4, 0xb2, 0x07, 0xe3, 0xce, 0xb6, 0x22, 0x51, 0xae, 0x15,
0x85, 0x84, 0x56, 0x9c, 0xa0, 0x2f, 0xad, 0x7c, 0x00, 0x9b, 0x6a, 0x96, 0x15, 0x27, 0x05, 0xb0,
0x15, 0x1f, 0x69, 0x71, 0xc5, 0xab, 0xb7, 0xa8, 0x5f, 0xff, 0x6c, 0xb0, 0x00, 0xdb, 0xa2, 0xf3,
0xb3, 0xbf, 0xd2, 0x92, 0x34, 0xc5, 0xb9, 0x69, 0xda, 0x4f, 0x87, 0xd0, 0x7c, 0xde, 0x4c, 0xd3,
0x7e, 0x66, 0x06, 0xad, 0xfc, 0x1b, 0x1a, 0x14, 0x9b, 0x50, 0x4f, 0xea, 0x19, 0x91, 0x78, 0xaf,
0xb1, 0xfd, 0xb0, 0xf8, 0x12, 0xfe, 0x5a, 0x6f, 0x34, 0x1e, 0x15, 0x35, 0x3d, 0x2b, 0x92, 0xeb,
0x5f, 0x3e, 0xd8, 0xd8, 0x2f, 0xc6, 0xf4, 0x82, 0xc8, 0x6d, 0x6e, 0xef, 0x6e, 0x6d, 0x98, 0x7b,
0xe6, 0xf6, 0xee, 0x41, 0x31, 0x8e, 0x7d, 0x9b, 0x8f, 0x1a, 0xf7, 0x0f, 0x8a, 0x09, 0x3d, 0x2d,
0xe2, 0xd8, 0x96, 0xd4, 0x85, 0x48, 0xed, 0x1f, 0x40, 0xff, 0x56, 0x31, 0x85, 0x56, 0x0e, 0xb6,
0x77, 0x36, 0x8a, 0x69, 0x44, 0x1e, 0xbc, 0xbb, 0xf7, 0x68, 0xa3, 0x98, 0xc1, 0x9f, 0xf7, 0x4d,
0xf3, 0xfe, 0x97, 0x8b, 0x59, 0x24, 0xed, 0xdc, 0xdf, 0x2b, 0x0a, 0xea, 0xbe, 0xbf, 0x0e, 0xdd,
0x39, 0x3d, 0x2f, 0x32, 0x9b, 0xef, 0xee, 0x3e, 0x38, 0xd8, 0x6e, 0xec, 0x16, 0xf3, 0xe5, 0xdf,
0x8c, 0x09, 0xb1, 0x65, 0xef, 0x3f, 0xe9, 0x0e, 0xa9, 0x2a, 0xbe, 0x2e, 0xc4, 0x18, 0x7e, 0x37,
0x49, 0x7a, 0x5c, 0xd9, 0x65, 0xb1, 0x85, 0x82, 0x8e, 0xfe, 0xaa, 0xc8, 0x53, 0x77, 0x5b, 0x86,
0x02, 0x2a, 0xe8, 0xd2, 0x66, 0x0e, 0xdb, 0x38, 0x3a, 0xf8, 0x21, 0xab, 0x35, 0xaa, 0xe3, 0x52,
0x0a, 0x64, 0xb5, 0x06, 0xf5, 0x3d, 0x3d, 0x36, 0xc7, 0x14, 0xd6, 0xa9, 0x76, 0xcb, 0x9a, 0x34,
0xae, 0x0c, 0xf4, 0x20, 0x72, 0x1a, 0x53, 0xca, 0xa2, 0x30, 0x2d, 0x51, 0xc7, 0xdd, 0x25, 0xfc,
0x21, 0x65, 0xe1, 0x11, 0x16, 0x1b, 0x22, 0xeb, 0xb6, 0xe3, 0x58, 0xd4, 0xca, 0x33, 0x2a, 0xd2,
0x8c, 0x04, 0x35, 0xb9, 0x53, 0x92, 0x00, 0xf6, 0x66, 0x81, 0xbc, 0x91, 0x24, 0xe9, 0x4e, 0xf9,
0xba, 0x98, 0xdb, 0xb5, 0x07, 0x72, 0x0b, 0xd1, 0x2a, 0xe5, 0x85, 0xd6, 0x2a, 0x69, 0x54, 0xc2,
0x68, 0xad, 0xf2, 0x0d, 0x21, 0x94, 0xbe, 0xa2, 0xd0, 0x0e, 0x65, 0x1f, 0x6d, 0x44, 0xed, 0xb0,
0xfc, 0xa6, 0x48, 0xed, 0xb4, 0x9e, 0x1f, 0xb4, 0x3a, 0x30, 0x96, 0xe8, 0xb5, 0xc6, 0x13, 0x58,
0x1b, 0x94, 0xca, 0xff, 0xc3, 0x3f, 0x8d, 0x4e, 0x5c, 0x59, 0x6c, 0x95, 0x52, 0x79, 0x2a, 0x44,
0xa3, 0x77, 0xb4, 0x63, 0x8d, 0xc7, 0xad, 0x8e, 0x05, 0xe7, 0x85, 0xd4, 0x00, 0x8c, 0x5a, 0x78,
0x4d, 0x81, 0xc5, 0xfc, 0x55, 0x6f, 0x15, 0x3c, 0xd4, 0xd2, 0x2e, 0x41, 0x4c, 0x86, 0x82, 0x07,
0xf1, 0xc1, 0x49, 0x9f, 0x2e, 0x2b, 0x92, 0x26, 0xfe, 0x5c, 0xbc, 0x26, 0x52, 0x12, 0x83, 0x97,
0x22, 0x83, 0x56, 0xdf, 0x2a, 0xc9, 0x71, 0xe9, 0x77, 0xf9, 0x57, 0x34, 0x21, 0x76, 0xad, 0x67,
0xe7, 0x18, 0xd3, 0x43, 0x45, 0x8c, 0x19, 0x97, 0x63, 0xbe, 0x13, 0x35, 0x26, 0xea, 0xac, 0x6d,
0xdb, 0x47, 0x4d, 0xf9, 0x8a, 0xe5, 0xbd, 0x4a, 0x16, 0x5b, 0xe8, 0xad, 0x95, 0x3f, 0x10, 0xf9,
0xed, 0xc1, 0xc0, 0x1a, 0x39, 0x3e, 0x81, 0x89, 0x63, 0x7b, 0x3c, 0xe1, 0x0b, 0x1e, 0xfa, 0xad,
0x97, 0x44, 0x62, 0x68, 0x8f, 0x26, 0x72, 0x9e, 0xf5, 0x04, 0x9c, 0x69, 0x96, 0x4d, 0x6a, 0xd1,
0xaf, 0x89, 0xec, 0x63, 0x1b, 0xe8, 0x8f, 0x71, 0x12, 0x71, 0xaa, 0x2d, 0xbc, 0x86, 0xf2, 0x2f,
0x69, 0x22, 0xdf, 0x98, 0x1c, 0x7b, 0xc6, 0xc1, 0xf7, 0x27, 0xd6, 0x29, 0xb9, 0x07, 0xbe, 0xc3,
0x4f, 0xbc, 0xda, 0xf9, 0xd9, 0x56, 0xef, 0x44, 0x5e, 0xf8, 0xe4, 0x4d, 0xf9, 0xa0, 0x5f, 0x12,
0xa9, 0x67, 0x56, 0xb7, 0x73, 0x3c, 0x21, 0x9b, 0x31, 0x93, 0x9f, 0xa0, 0x4c, 0x48, 0x76, 0xd1,
0xd9, 0x52, 0x82, 0xd6, 0xeb, 0x92, 0xb7, 0x5e, 0xea, 0x1c, 0x4c, 0x09, 0xba, 0x93, 0xc9, 0x1c,
0x15, 0x7f, 0x01, 0xfe, 0xc5, 0xca, 0x6d, 0x71, 0xd1, 0x89, 0x1d, 0xbe, 0xc9, 0xee, 0x8a, 0x52,
0xcf, 0xb2, 0x41, 0x24, 0x10, 0x65, 0x7a, 0xa7, 0xcd, 0x67, 0xf6, 0xa0, 0xd9, 0x1a, 0x34, 0xed,
0xf1, 0xe3, 0xd6, 0x88, 0x16, 0x20, 0x7c, 0x88, 0x8b, 0xc0, 0xdb, 0x94, 0xb4, 0xf7, 0xed, 0xc1,
0xfd, 0x41, 0x03, 0x39, 0xe5, 0xdf, 0x4f, 0x88, 0xec, 0xce, 0xa9, 0x63, 0x1d, 0xe6, 0xf6, 0xd8,
0x3e, 0x19, 0xc8, 0xb5, 0x4c, 0x9a, 0xf2, 0xc1, 0x7d, 0x47, 0x31, 0xe5, 0x1d, 0x01, 0xf2, 0xe9,
0x89, 0x3d, 0xb1, 0x68, 0xba, 0x59, 0x53, 0x3e, 0xe0, 0x6a, 0x0d, 0xad, 0x09, 0xcc, 0x15, 0x2b,
0x4c, 0xfc, 0xe9, 0xcd, 0x3f, 0x79, 0x8e, 0xf9, 0xc3, 0x39, 0x3b, 0x65, 0xe3, 0xea, 0x8f, 0x4b,
0x29, 0xba, 0xdc, 0x52, 0xe0, 0xea, 0x5b, 0x31, 0x19, 0xa5, 0x6f, 0x8b, 0x85, 0x67, 0x56, 0xb3,
0x7f, 0x02, 0xdb, 0xa6, 0x63, 0xc3, 0x19, 0x0c, 0xa2, 0xf6, 0x08, 0x82, 0x0a, 0x8e, 0xa4, 0xc4,
0x84, 0x59, 0x0b, 0x69, 0xce, 0x3f, 0xb3, 0x76, 0x80, 0xb7, 0x65, 0x3f, 0x24, 0x16, 0x28, 0x3b,
0x0b, 0x29, 0xa8, 0x29, 0x9d, 0xcd, 0x07, 0x47, 0xf7, 0x51, 0x33, 0x00, 0xa4, 0x06, 0x7d, 0x45,
0x64, 0x0e, 0xbb, 0x4f, 0xac, 0xf1, 0x31, 0x68, 0x29, 0x0d, 0xc3, 0xce, 0x1b, 0x57, 0x3c, 0x8e,
0xbb, 0xac, 0x4b, 0x0f, 0xec, 0x9e, 0x3d, 0x32, 0x5d, 0x28, 0x1c, 0x11, 0xb2, 0x63, 0xbb, 0x6f,
0x49, 0x7d, 0x67, 0x28, 0xb3, 0x5d, 0x9f, 0xc5, 0xdb, 0x07, 0x90, 0x13, 0xc1, 0x1c, 0xbc, 0x7e,
0x55, 0x3a, 0x7a, 0x88, 0xe7, 0xd7, 0x92, 0xa0, 0xfa, 0x1c, 0x1d, 0xa2, 0xf3, 0xac, 0xbe, 0x88,
0x0e, 0x75, 0xda, 0x78, 0x2c, 0x81, 0x00, 0x8d, 0xc5, 0x9d, 0xfb, 0xbc, 0xf8, 0x16, 0x84, 0x3e,
0xc7, 0xa0, 0x17, 0xfa, 0x64, 0xb8, 0xc9, 0x52, 0x3c, 0x90, 0xa1, 0x4f, 0xc6, 0x9a, 0xd7, 0x44,
0x92, 0xdc, 0xc6, 0x34, 0x61, 0x6e, 0x60, 0x56, 0x82, 0x34, 0xb1, 0x65, 0x6e, 0x6c, 0xec, 0x42,
0x5a, 0xc2, 0x04, 0xf5, 0xe8, 0xdd, 0x8d, 0x62, 0x4c, 0x51, 0xec, 0x6f, 0x69, 0x22, 0xbe, 0xf1,
0x9c, 0xd4, 0x82, 0xd3, 0x70, 0x76, 0x34, 0xfe, 0x36, 0x56, 0x45, 0xa2, 0x6f, 0x8f, 0x2c, 0xfd,
0xc2, 0x8c, 0x59, 0x96, 0x3a, 0xf4, 0xbe, 0x94, 0xab, 0x5c, 0xb0, 0x62, 0x12, 0xde, 0x78, 0x43,
0x24, 0x26, 0x16, 0xd8, 0x9c, 0xc9, 0x3b, 0x96, 0x03, 0x20, 0xc0, 0x80, 0x30, 0x0a, 0x71, 0xe5,
0x10, 0x5e, 0xc9, 0x4c, 0x68, 0x97, 0xa6, 0xc7, 0x90, 0xf2, 0x7b, 0xa2, 0xf8, 0xc0, 0xee, 0x0f,
0x7b, 0xd6, 0x73, 0x18, 0xc9, 0x1a, 0x8c, 0x21, 0x65, 0xa3, 0x9e, 0xdb, 0xdd, 0x11, 0x45, 0x11,
0xba, 0xb0, 0xa5, 0x07, 0xdc, 0xd5, 0x63, 0x0b, 0xa2, 0xc3, 0x11, 0x07, 0x4c, 0x7e, 0x42, 0xf4,
0xe4, 0xb8, 0x3b, 0xc2, 0x00, 0x82, 0x71, 0x5e, 0x3e, 0x94, 0xb7, 0x44, 0x81, 0x0f, 0xfa, 0x63,
0x1e, 0xb8, 0x7c, 0x47, 0xe4, 0x9d, 0x26, 0xba, 0xbd, 0x86, 0x85, 0xfb, 0x60, 0xc3, 0x6c, 0xc0,
0x6a, 0xc2, 0xb2, 0x36, 0x76, 0x37, 0x60, 0x2d, 0xe1, 0xc7, 0xc1, 0xfb, 0x0d, 0xdf, 0x52, 0x5e,
0x13, 0x79, 0xd7, 0xf7, 0x7d, 0x6b, 0x42, 0x3d, 0x98, 0x10, 0xd2, 0xf5, 0x58, 0x46, 0x2b, 0xa7,
0x45, 0x72, 0xa3, 0x3f, 0x9c, 0x9c, 0x96, 0x7f, 0x5e, 0xe4, 0x18, 0xf4, 0xa8, 0x0b, 0xce, 0xae,
0x89, 0x74, 0x9f, 0xe7, 0xab, 0xd1, 0x99, 0x4b, 0xd5, 0x94, 0x87, 0x73, 0x7e, 0x9b, 0x0e, 0x7a,
0xb1, 0x2a, 0xd2, 0x4a, 0x2c, 0xe5, 0xad, 0x1e, 0x53, 0xb7, 0xba, 0x0c, 0x0a, 0x71, 0x25, 0x28,
0x94, 0x77, 0x44, 0x5a, 0x66, 0xc0, 0x31, 0x65, 0x75, 0x59, 0xaf, 0x49, 0x31, 0xc9, 0x37, 0x9f,
0x93, 0x6d, 0xf2, 0x0a, 0x19, 0xe4, 0x46, 0x82, 0x65, 0x84, 0x0c, 0x9d, 0x82, 0x9a, 0xa4, 0xdc,
0x7e, 0x2f, 0x29, 0x32, 0xce, 0x4a, 0x81, 0xc4, 0x53, 0xb2, 0x48, 0x22, 0x53, 0x4e, 0x11, 0x9f,
0xa4, 0xb2, 0x08, 0x3a, 0xd3, 0x5c, 0x08, 0x71, 0x74, 0xc7, 0x8a, 0x3d, 0x25, 0x0b, 0x1f, 0xb7,
0x13, 0xce, 0x16, 0x71, 0xb7, 0x3c, 0x4f, 0xc9, 0xd2, 0x46, 0xbf, 0x29, 0xb2, 0x6e, 0x31, 0x43,
0xf1, 0x98, 0x6b, 0xf1, 0x8c, 0x53, 0xbd, 0x28, 0x08, 0x30, 0x90, 0xf4, 0x0a, 0xef, 0x4c, 0xdb,
0x3b, 0x9e, 0x64, 0x9c, 0x92, 0x84, 0xee, 0xd0, 0x9d, 0x2a, 0x3b, 0xcd, 0x45, 0x88, 0x07, 0x00,
0x0b, 0x69, 0xa5, 0xa4, 0x4e, 0x73, 0xa1, 0x01, 0x80, 0x34, 0x97, 0x16, 0xb4, 0xf5, 0xbd, 0xfa,
0x39, 0x25, 0xcb, 0x09, 0x58, 0xce, 0x8c, 0x53, 0x40, 0xd0, 0xbe, 0xf4, 0x8a, 0xe5, 0x34, 0x17,
0x0d, 0xfa, 0x9b, 0x08, 0x91, 0xcb, 0x0f, 0x21, 0x60, 0x76, 0x65, 0x9c, 0xe6, 0xca, 0x18, 0x26,
0x95, 0xe6, 0x82, 0x98, 0x42, 0x82, 0x52, 0x05, 0xa7, 0x64, 0x15, 0xac, 0xdf, 0x20, 0x73, 0x72,
0x52, 0x79, 0xaf, 0xe2, 0x4d, 0x73, 0x95, 0xe1, 0xf5, 0xd3, 0x91, 0xcd, 0xad, 0x6e, 0xd3, 0x5c,
0x47, 0xe8, 0xab, 0xf8, 0xbe, 0x50, 0xdf, 0x70, 0x5c, 0xc3, 0x20, 0x58, 0xf2, 0x84, 0xe7, 0xbc,
0x53, 0x19, 0x03, 0xeb, 0x32, 0x82, 0xc0, 0xab, 0xa4, 0xdd, 0xb0, 0x88, 0xbc, 0xbd, 0xee, 0xa0,
0x0d, 0xe7, 0x38, 0x5c, 0x89, 0x38, 0xfc, 0x84, 0x3e, 0x6c, 0x91, 0x1a, 0xd8, 0xc5, 0xbe, 0x22,
0xf5, 0x25, 0xde, 0x96, 0x9d, 0xd8, 0x04, 0xe9, 0x3d, 0x09, 0x9d, 0xad, 0x01, 0x1c, 0xc8, 0x88,
0x37, 0x68, 0x0d, 0xcc, 0x44, 0x1b, 0x1a, 0xf4, 0x37, 0x44, 0x7c, 0x7c, 0x72, 0x58, 0xd2, 0x83,
0x9f, 0x37, 0xf6, 0x4f, 0x0e, 0x1d, 0x57, 0x4c, 0x44, 0x80, 0xfd, 0x0c, 0x08, 0xb4, 0xf9, 0x73,
0xd6, 0xc8, 0x2e, 0x5d, 0xa0, 0x25, 0x7c, 0xc9, 0x4c, 0x43, 0xcb, 0x07, 0xd0, 0x70, 0xce, 0xe0,
0x07, 0x87, 0xbb, 0x9c, 0x62, 0x17, 0x4e, 0xe8, 0xda, 0x40, 0x9e, 0x14, 0xea, 0xda, 0x9a, 0xa9,
0x0d, 0xca, 0x07, 0x22, 0xef, 0x14, 0x12, 0x34, 0x5f, 0x03, 0x77, 0x12, 0x98, 0xa5, 0xfd, 0x39,
0x6f, 0x5c, 0x53, 0x53, 0x94, 0x07, 0xe3, 0x74, 0x21, 0xa1, 0xe5, 0x62, 0xc0, 0x15, 0xad, 0xfc,
0x03, 0x38, 0xa3, 0xec, 0x40, 0x74, 0x74, 0x2f, 0x4d, 0x61, 0x83, 0x1e, 0xc2, 0xce, 0x18, 0x93,
0xd9, 0x8c, 0x29, 0x1f, 0xf4, 0xd7, 0x44, 0x9e, 0x7e, 0x38, 0x05, 0x60, 0xcc, 0xbd, 0x5f, 0xc8,
0x51, 0x3b, 0x57, 0x7d, 0xb0, 0xe3, 0xe1, 0x25, 0x8e, 0x39, 0x92, 0xd1, 0x6f, 0xfd, 0x33, 0x22,
0x87, 0x7f, 0x1d, 0x66, 0xc2, 0x3d, 0xb0, 0x0a, 0x6c, 0x66, 0xe2, 0x1b, 0x62, 0x8e, 0xde, 0xbe,
0x0b, 0x4b, 0xbb, 0x77, 0x09, 0x79, 0xd9, 0xc1, 0xc0, 0x92, 0x48, 0xcb, 0x50, 0x30, 0xa6, 0x4f,
0x56, 0x59, 0xd3, 0x79, 0xc4, 0xf0, 0x4a, 0x95, 0x80, 0x4c, 0xf7, 0x69, 0x93, 0x9f, 0xca, 0xf7,
0x45, 0x86, 0xb2, 0x14, 0x1c, 0x63, 0xf5, 0xb2, 0xd0, 0x3a, 0x25, 0x8b, 0x72, 0xe4, 0x45, 0xe5,
0x98, 0xcf, 0xdd, 0x4b, 0x5b, 0xa6, 0xd6, 0x59, 0x5c, 0x10, 0xda, 0x16, 0x9e, 0xbb, 0x9f, 0x73,
0x98, 0xd6, 0x9e, 0x97, 0x1b, 0x6c, 0x02, 0x4e, 0xa5, 0x51, 0x26, 0xa0, 0x5b, 0x9a, 0x78, 0x65,
0xca, 0x04, 0x3e, 0x9d, 0xf2, 0xf7, 0x3b, 0xed, 0x14, 0xcf, 0xf9, 0xb4, 0x3d, 0xc1, 0xf1, 0x3d,
0x1b, 0xe6, 0x87, 0xdd, 0x6d, 0x3a, 0x27, 0xc1, 0x39, 0xbe, 0x5d, 0xfe, 0x34, 0x21, 0xe6, 0x39,
0x88, 0xbe, 0xdf, 0x9d, 0x1c, 0xef, 0xb4, 0x86, 0xfa, 0x23, 0x91, 0xc7, 0xf8, 0xd9, 0xec, 0xb7,
0x86, 0x43, 0xdc, 0xa8, 0x1a, 0x1d, 0x2a, 0x6e, 0x4f, 0x05, 0x65, 0xc6, 0x2f, 0xed, 0x02, 0x78,
0x47, 0x62, 0x37, 0x06, 0x93, 0xd1, 0xa9, 0x99, 0x1b, 0x78, 0x2d, 0x70, 0xd4, 0xc9, 0xf5, 0xc7,
0x1d, 0xd7, 0x58, 0x8c, 0x8c, 0xdd, 0x0a, 0x35, 0xb6, 0x33, 0xee, 0xf8, 0x6c, 0x89, 0xbe, 0xdb,
0x80, 0x8e, 0x61, 0xe4, 0x75, 0x6d, 0xc5, 0xcf, 0x70, 0x0c, 0x83, 0x84, 0xdf, 0xb1, 0x43, 0xaf,
0x05, 0x4a, 0x75, 0x81, 0x1b, 0x69, 0x62, 0x63, 0x91, 0x44, 0x5a, 0xc9, 0x19, 0xaf, 0x87, 0xda,
0x82, 0x98, 0x74, 0x60, 0xc3, 0x7f, 0xa4, 0x21, 0xdc, 0x82, 0xf4, 0xb8, 0xf8, 0x05, 0x51, 0x0c,
0xce, 0x5f, 0x3d, 0x7b, 0x27, 0x67, 0x9c, 0xbd, 0xb3, 0x7c, 0xf6, 0xae, 0xc7, 0xee, 0x6a, 0x8b,
0xef, 0x89, 0x42, 0x60, 0xca, 0x2a, 0x5d, 0x97, 0xf4, 0xb7, 0x55, 0x7a, 0xce, 0xb8, 0xac, 0x7c,
0x3d, 0x56, 0x5f, 0xad, 0x6a, 0x17, 0xfc, 0x0a, 0x4e, 0x5f, 0x35, 0x9c, 0x89, 0xa8, 0x09, 0x88,
0xff, 0x8e, 0x98, 0xf3, 0x4d, 0x59, 0x25, 0x67, 0xcf, 0x98, 0x54, 0xf9, 0x17, 0x93, 0x22, 0xd9,
0x18, 0x58, 0x76, 0x5b, 0xbf, 0xec, 0xcf, 0x88, 0x5f, 0x7c, 0xc9, 0xc9, 0x86, 0x57, 0x02, 0xd9,
0x10, 0x7a, 0x9c, 0x5c, 0x78, 0x25, 0x90, 0x0b, 0x9d, 0x2e, 0x08, 0xd8, 0xd7, 0xa7, 0x32, 0x21,
0x74, 0x7a, 0x69, 0xf0, 0xfa, 0x54, 0x1a, 0xf4, 0xba, 0x81, 0x7d, 0x35, 0x98, 0x03, 0xa1, 0xd7,
0xcd, 0x7f, 0x57, 0x83, 0xf9, 0xcf, 0xed, 0x04, 0xe6, 0x95, 0x40, 0xee, 0x23, 0x97, 0x64, 0xd6,
0xbb, 0x1a, 0xcc, 0x7a, 0xc4, 0xe3, 0x7c, 0x77, 0x35, 0x98, 0xef, 0xa8, 0x93, 0xf3, 0xdb, 0x95,
0x40, 0x7e, 0x23, 0xa3, 0x32, 0xb1, 0x5d, 0x0d, 0x26, 0x36, 0xc9, 0x53, 0x3c, 0x55, 0xb3, 0x9a,
0xdb, 0x09, 0x9e, 0x1a, 0x81, 0x94, 0x16, 0x7e, 0xae, 0xa7, 0x77, 0x41, 0xe1, 0xbd, 0x86, 0xcb,
0xe6, 0x1c, 0x39, 0x0b, 0x11, 0x1f, 0xd8, 0x69, 0x35, 0x9d, 0x23, 0x97, 0x21, 0xd2, 0x6d, 0x2e,
0x75, 0x8b, 0x14, 0xa3, 0x14, 0x59, 0xd2, 0xcb, 0x5f, 0xda, 0x6c, 0x52, 0xac, 0xa2, 0x79, 0xc9,
0xd3, 0xfb, 0x2d, 0x08, 0x46, 0xcd, 0x47, 0xad, 0x51, 0x07, 0x80, 0xcd, 0x83, 0x56, 0xc7, 0xbd,
0x2e, 0xc0, 0xf7, 0x9f, 0x6b, 0x73, 0x0f, 0xde, 0x2a, 0x5c, 0x72, 0xc4, 0x75, 0x44, 0xbd, 0x1a,
0xcb, 0x6b, 0xf1, 0x32, 0x2e, 0x9a, 0x34, 0x46, 0x51, 0x6f, 0x81, 0xa3, 0xde, 0x3a, 0x9c, 0x2e,
0x4f, 0x06, 0x70, 0x22, 0x5e, 0xcf, 0x8a, 0xf4, 0xc4, 0x1e, 0xf5, 0x5b, 0x13, 0xbb, 0xfc, 0x43,
0x4d, 0x08, 0x38, 0x31, 0xf7, 0xa1, 0xe3, 0x29, 0xd4, 0xba, 0x90, 0xf6, 0xfa, 0xad, 0x27, 0x10,
0x3f, 0xac, 0xe6, 0xe3, 0x91, 0xb3, 0x0f, 0xb2, 0xd8, 0xb4, 0x63, 0x3d, 0x00, 0x89, 0x97, 0x9c,
0xc3, 0x38, 0x69, 0x87, 0x24, 0xc9, 0x87, 0xf3, 0x8b, 0x7c, 0xbc, 0x4c, 0xf1, 0x3b, 0x74, 0x0e,
0x98, 0xb2, 0x62, 0x48, 0xf3, 0xdb, 0xa3, 0x27, 0x94, 0xfc, 0xc4, 0xea, 0x0f, 0x9b, 0x8f, 0x49,
0x2a, 0x28, 0x87, 0x24, 0x3e, 0x3f, 0x80, 0x5d, 0x1c, 0x87, 0xd4, 0x48, 0x22, 0x39, 0xe3, 0xbd,
0x20, 0x0e, 0xf2, 0x60, 0x1c, 0x62, 0x1f, 0xc9, 0x26, 0x67, 0x2c, 0x28, 0x27, 0x02, 0x99, 0x84,
0x10, 0x06, 0xfd, 0xee, 0xbc, 0xef, 0x14, 0x44, 0x7c, 0xb3, 0xd1, 0xc0, 0x2c, 0x0f, 0x7f, 0x2a,
0x45, 0xad, 0xfe, 0x39, 0x91, 0xe9, 0x8c, 0x2c, 0x0b, 0xc3, 0xc3, 0xec, 0xea, 0xe2, 0x43, 0xca,
0x6a, 0x2e, 0xa8, 0x0e, 0x47, 0xe3, 0xc7, 0xb2, 0xbe, 0xd0, 0x43, 0x0a, 0xd8, 0xd2, 0x1f, 0xc8,
0xeb, 0x93, 0x45, 0xaf, 0x3b, 0x58, 0x91, 0x98, 0x8e, 0x8d, 0xfa, 0x1e, 0x14, 0x7c, 0xcd, 0xb3,
0x0c, 0x7e, 0x24, 0xb3, 0x4b, 0x94, 0xc1, 0xcc, 0x88, 0x9b, 0xea, 0x1b, 0x62, 0x61, 0x60, 0x3b,
0x9f, 0x2c, 0x9a, 0x47, 0x72, 0x8f, 0x5d, 0x99, 0x3e, 0xb4, 0x39, 0xc6, 0x2d, 0xf9, 0x99, 0x70,
0x60, 0x73, 0x87, 0xdc, 0x95, 0xf5, 0x07, 0xa2, 0xa8, 0x98, 0xa1, 0x22, 0x33, 0xca, 0x4a, 0x5b,
0x7e, 0x97, 0x74, 0xad, 0xd0, 0xbe, 0x0f, 0x18, 0x91, 0x3b, 0x33, 0xc2, 0x48, 0x47, 0x7e, 0xe4,
0x75, 0x8d, 0x50, 0xa8, 0x9b, 0x36, 0x82, 0xb1, 0x26, 0xdc, 0xc8, 0xb1, 0xfc, 0xfe, 0xab, 0x1a,
0x59, 0xad, 0x05, 0x56, 0xe5, 0xe4, 0x4c, 0x57, 0xba, 0xf2, 0xf3, 0xad, 0x6b, 0x45, 0x06, 0xc0,
0x19, 0x66, 0xa2, 0x9d, 0xf9, 0x50, 0x7e, 0xd9, 0xf5, 0x99, 0x99, 0xf2, 0x66, 0x7c, 0xa6, 0x37,
0x4f, 0xe4, 0x67, 0x54, 0xd7, 0xcc, 0xfe, 0x2c, 0x6f, 0xc6, 0x67, 0x7a, 0xd3, 0x93, 0x1f, 0x58,
0x7d, 0x66, 0xc0, 0x9b, 0x2d, 0xa1, 0xab, 0xaf, 0x9a, 0xf3, 0x44, 0x84, 0x9d, 0xbe, 0xfc, 0x6c,
0xee, 0xbd, 0x6c, 0x49, 0x99, 0x65, 0x28, 0xda, 0xa1, 0x81, 0xfc, 0xa2, 0xee, 0x37, 0x04, 0x1e,
0x6d, 0x8b, 0x0b, 0xea, 0xc4, 0xce, 0xe1, 0x92, 0x0d, 0x96, 0x0a, 0xe6, 0x82, 0x37, 0x35, 0xe6,
0xcc, 0x34, 0x15, 0xed, 0xd4, 0x10, 0x4c, 0x15, 0xa7, 0x4c, 0x81, 0x57, 0xf7, 0x45, 0x41, 0x31,
0x75, 0x48, 0x19, 0x3a, 0xdc, 0xcc, 0x53, 0xf9, 0xbf, 0x36, 0xb8, 0x66, 0x30, 0xa3, 0x07, 0xdf,
0x18, 0xe7, 0xb8, 0x70, 0x23, 0x23, 0xf9, 0x5d, 0xde, 0xf3, 0x85, 0x18, 0x81, 0x2d, 0x41, 0x95,
0x76, 0x94, 0x95, 0xb1, 0xfc, 0x62, 0xef, 0xb9, 0x82, 0x84, 0x7a, 0xd7, 0x37, 0x1d, 0x0b, 0x93,
0x5c, 0x84, 0x8d, 0x09, 0x45, 0xe4, 0xd7, 0x43, 0x01, 0x4b, 0xea, 0x55, 0x88, 0x32, 0x6d, 0x7c,
0x84, 0x97, 0x30, 0x7f, 0xfe, 0x80, 0xf4, 0x91, 0x26, 0xeb, 0xe2, 0xea, 0x12, 0x96, 0xce, 0xe6,
0xdc, 0x91, 0x2f, 0x2e, 0x6d, 0x88, 0xb9, 0x73, 0x07, 0xa5, 0x8f, 0x35, 0x59, 0x5d, 0xa2, 0x25,
0x33, 0x7f, 0xe4, 0x8f, 0x4c, 0x73, 0xe7, 0x0e, 0x4b, 0x9f, 0x68, 0xf2, 0x2a, 0xa2, 0x66, 0xb8,
0x46, 0x9c, 0xc8, 0x34, 0x77, 0xee, 0xb0, 0xf4, 0x15, 0x59, 0x3b, 0xc6, 0x6a, 0x55, 0xd5, 0x08,
0xc5, 0x82, 0xf9, 0xf3, 0x87, 0xa5, 0xaf, 0x6a, 0x74, 0x2d, 0x11, 0xab, 0xd5, 0xdc, 0x75, 0x71,
0x23, 0xd3, 0xfc, 0xf9, 0xc3, 0xd2, 0xd7, 0x34, 0xba, 0xbc, 0x88, 0xd5, 0x56, 0x7c, 0x66, 0xfc,
0xde, 0x9c, 0x1d, 0x96, 0xbe, 0xae, 0xd1, 0x7d, 0x42, 0xac, 0xb6, 0xea, 0x9a, 0xd9, 0x9f, 0xf2,
0xe6, 0xec, 0xb0, 0xf4, 0x0d, 0x3a, 0xc5, 0x83, 0x99, 0x35, 0x9f, 0x19, 0x8a, 0x4c, 0x85, 0x17,
0x08, 0x4b, 0xdf, 0xd4, 0xe8, 0xda, 0x27, 0x56, 0xbb, 0x6b, 0x3a, 0xa3, 0x7b, 0x91, 0xa9, 0xf0,
0x02, 0x61, 0xe9, 0x53, 0x8d, 0x6e, 0x87, 0x62, 0xb5, 0x7b, 0x7e, 0x43, 0x14, 0x99, 0x8a, 0x2f,
0x12, 0x96, 0xbe, 0x85, 0x96, 0x0a, 0xf5, 0xd8, 0xca, 0xb2, 0xe9, 0x38, 0xa0, 0x44, 0xa6, 0xe2,
0x8b, 0x84, 0xa5, 0x6f, 0xa3, 0xa9, 0x22, 0x98, 0xaa, 0x04, 0x4c, 0x81, 0x57, 0x0f, 0x44, 0xfe,
0xbc, 0x61, 0xe9, 0x3b, 0xea, 0xad, 0x5b, 0xee, 0x48, 0x89, 0x4d, 0x7b, 0xca, 0x3b, 0x3b, 0x33,
0x30, 0x7d, 0x97, 0x6a, 0x9c, 0xfa, 0xdc, 0x17, 0xe5, 0xcd, 0x94, 0x24, 0x78, 0xaf, 0x4f, 0x86,
0xa9, 0x1d, 0x6f, 0x7f, 0x9c, 0x19, 0xa3, 0xbe, 0xa7, 0xd1, 0xf5, 0x55, 0x9e, 0x0d, 0x12, 0xde,
0xdd, 0x29, 0x32, 0x60, 0x7d, 0xe8, 0xcd, 0xf2, 0xac, 0x68, 0xf5, 0x7d, 0xed, 0x45, 0xc2, 0x55,
0x1d, 0x6f, 0x6b, 0xdd, 0xc5, 0xa0, 0x96, 0xcf, 0x8b, 0xc4, 0x73, 0x63, 0xb9, 0xa2, 0x1e, 0xc9,
0xd4, 0x5b, 0x5b, 0x19, 0xa4, 0x72, 0x46, 0x41, 0xb9, 0xd8, 0xc6, 0x6b, 0x5b, 0x93, 0x58, 0xcc,
0x36, 0x42, 0xd9, 0x1f, 0x47, 0xb0, 0x0d, 0x66, 0x57, 0x43, 0xd9, 0x9f, 0x44, 0xb0, 0xab, 0xcc,
0xae, 0x85, 0xb2, 0xbf, 0x12, 0xc1, 0xae, 0x31, 0x7b, 0x25, 0x94, 0xfd, 0xd5, 0x08, 0xf6, 0x0a,
0xb3, 0x57, 0x43, 0xd9, 0x5f, 0x8b, 0x60, 0xaf, 0x32, 0x7b, 0x2d, 0x94, 0xfd, 0xf5, 0x08, 0xf6,
0x1a, 0xb3, 0xef, 0x86, 0xb2, 0xbf, 0x11, 0xc1, 0xbe, 0xcb, 0xec, 0x7b, 0xa1, 0xec, 0x6f, 0x46,
0xb0, 0xef, 0x49, 0x76, 0x65, 0x39, 0x94, 0xfd, 0x69, 0x38, 0xbb, 0xb2, 0xcc, 0xec, 0x70, 0xad,
0x7d, 0x2b, 0x82, 0xcd, 0x5a, 0xab, 0x84, 0x6b, 0xed, 0xdb, 0x11, 0x6c, 0xd6, 0x5a, 0x25, 0x5c,
0x6b, 0xdf, 0x89, 0x60, 0xb3, 0xd6, 0x2a, 0xe1, 0x5a, 0xfb, 0x6e, 0x04, 0x9b, 0xb5, 0x56, 0x09,
0xd7, 0xda, 0xf7, 0x22, 0xd8, 0xac, 0xb5, 0x4a, 0xb8, 0xd6, 0xbe, 0x1f, 0xc1, 0x66, 0xad, 0x55,
0xc2, 0xb5, 0xf6, 0x87, 0x11, 0x6c, 0xd6, 0x5a, 0x25, 0x5c, 0x6b, 0x7f, 0x14, 0xc1, 0x66, 0xad,
0x55, 0xc2, 0xb5, 0xf6, 0xc7, 0x11, 0x6c, 0xd6, 0x9a, 0x11, 0xae, 0xb5, 0x3f, 0x09, 0x67, 0x1b,
0xac, 0x35, 0x23, 0x5c, 0x6b, 0x7f, 0x1a, 0xc1, 0x66, 0xad, 0x19, 0xe1, 0x5a, 0xfb, 0xb3, 0x08,
0x36, 0x6b, 0xcd, 0x08, 0xd7, 0xda, 0x0f, 0x22, 0xd8, 0xac, 0x35, 0x23, 0x5c, 0x6b, 0x7f, 0x1e,
0xc1, 0x66, 0xad, 0x19, 0xe1, 0x5a, 0xfb, 0x8b, 0x08, 0x36, 0x6b, 0xcd, 0x08, 0xd7, 0xda, 0x5f,
0x46, 0xb0, 0x59, 0x6b, 0x46, 0xb8, 0xd6, 0xfe, 0x2a, 0x82, 0xcd, 0x5a, 0x33, 0xc2, 0xb5, 0xf6,
0xd7, 0x11, 0x6c, 0xd6, 0x9a, 0x11, 0xae, 0xb5, 0xbf, 0x89, 0x60, 0xb3, 0xd6, 0xaa, 0xe1, 0x5a,
0xfb, 0xdb, 0x70, 0x76, 0x95, 0xb5, 0x56, 0x0d, 0xd7, 0xda, 0xdf, 0x45, 0xb0, 0x59, 0x6b, 0xd5,
0x70, 0xad, 0xfd, 0x7d, 0x04, 0x9b, 0xb5, 0x56, 0x0d, 0xd7, 0xda, 0x3f, 0x44, 0xb0, 0x59, 0x6b,
0xd5, 0x70, 0xad, 0xfd, 0x30, 0x82, 0xcd, 0x5a, 0xab, 0x86, 0x6b, 0xed, 0x1f, 0x23, 0xd8, 0xac,
0xb5, 0x6a, 0xb8, 0xd6, 0xfe, 0x29, 0x82, 0xcd, 0x5a, 0xab, 0x86, 0x6b, 0xed, 0x9f, 0x23, 0xd8,
0xac, 0xb5, 0x6a, 0xb8, 0xd6, 0xfe, 0x25, 0x82, 0xcd, 0x5a, 0xab, 0x86, 0x6b, 0xed, 0x5f, 0x23,
0xd8, 0xac, 0xb5, 0x5a, 0xb8, 0xd6, 0xfe, 0x2d, 0x9c, 0x5d, 0x63, 0xad, 0xd5, 0xc2, 0xb5, 0xf6,
0xef, 0x11, 0x6c, 0xd6, 0x5a, 0x2d, 0x5c, 0x6b, 0xff, 0x11, 0xc1, 0x66, 0xad, 0xd5, 0xc2, 0xb5,
0xf6, 0x9f, 0x11, 0x6c, 0xd6, 0x5a, 0x2d, 0x5c, 0x6b, 0xff, 0x15, 0xc1, 0x66, 0xad, 0xd5, 0xc2,
0xb5, 0xf6, 0xdf, 0x11, 0x6c, 0xd6, 0x5a, 0x2d, 0x5c, 0x6b, 0x3f, 0x8a, 0x60, 0xb3, 0xd6, 0x6a,
0xe1, 0x5a, 0xfb, 0x71, 0x04, 0x9b, 0xb5, 0x56, 0x0b, 0xd7, 0xda, 0xff, 0x44, 0xb0, 0x59, 0x6b,
0xb5, 0x70, 0xad, 0xfd, 0x6f, 0x04, 0x9b, 0xb5, 0xb6, 0x12, 0xae, 0xb5, 0xff, 0x0b, 0x67, 0xaf,
0x2c, 0xff, 0x24, 0x00, 0x00, 0xff, 0xff, 0x81, 0x23, 0xc6, 0xe6, 0xc6, 0x38, 0x00, 0x00,
0x96, 0xea, 0xf1, 0xaa, 0x71, 0xd7, 0x5c, 0x70, 0x04, 0x35, 0x8b, 0xe4, 0x1b, 0xe6, 0x2d, 0x94,
0x54, 0x3d, 0xbe, 0x52, 0x73, 0x49, 0xea, 0x48, 0x06, 0xca, 0x90, 0x85, 0xe5, 0x71, 0xde, 0x46,
0x65, 0xd5, 0x13, 0x30, 0xd0, 0x5d, 0x10, 0xa3, 0xec, 0x9e, 0xc1, 0xf1, 0x8d, 0xb3, 0x84, 0x0a,
0xab, 0x27, 0x60, 0x1c, 0x87, 0xe3, 0x1f, 0x67, 0xc1, 0x11, 0x9a, 0x47, 0xf9, 0x1c, 0x2a, 0xad,
0x9e, 0xaa, 0x56, 0x6a, 0x95, 0xe5, 0xfb, 0xb0, 0x0a, 0xd4, 0xef, 0x71, 0x6a, 0x38, 0x0e, 0x4b,
0xce, 0x23, 0xdd, 0x45, 0xcd, 0xd5, 0x53, 0xc6, 0x6a, 0xe5, 0x9e, 0x71, 0x0f, 0x46, 0x92, 0x00,
0x8f, 0xf5, 0x05, 0x64, 0xb1, 0xf8, 0x3c, 0x56, 0x05, 0xd5, 0x57, 0x2f, 0x1e, 0x5b, 0xbd, 0x9e,
0xfd, 0xd6, 0xcd, 0xf2, 0x33, 0x7b, 0xd4, 0x3b, 0x7a, 0xb5, 0x2c, 0x80, 0x2f, 0xa1, 0xea, 0xa8,
0x0b, 0x8e, 0x20, 0x3d, 0xfa, 0xaf, 0xe2, 0x39, 0x2c, 0x5f, 0x4f, 0xaf, 0x75, 0x3b, 0x03, 0x7b,
0x6c, 0x81, 0xaf, 0x84, 0x08, 0xac, 0xc9, 0x5e, 0x70, 0x1d, 0x7f, 0x0d, 0x69, 0x0b, 0xf5, 0xf8,
0xdb, 0x20, 0x8a, 0x22, 0x2b, 0x74, 0x06, 0xc7, 0xb7, 0x8e, 0xbf, 0x8e, 0x1c, 0x1d, 0x38, 0x20,
0x8c, 0x22, 0x0b, 0xd5, 0xe3, 0xac, 0x8a, 0x4b, 0x81, 0xbc, 0xd8, 0x1c, 0xb6, 0x0e, 0x9f, 0x00,
0xcf, 0xc0, 0xf4, 0xb8, 0x16, 0x2b, 0x6a, 0xe6, 0x05, 0x5f, 0x8a, 0xdc, 0xa5, 0x6e, 0xfd, 0xbe,
0xb8, 0x1c, 0x4c, 0x94, 0x0e, 0xb3, 0x8a, 0xf9, 0x92, 0x98, 0x17, 0xfd, 0x39, 0x33, 0x40, 0x55,
0x02, 0xb0, 0x43, 0xad, 0x61, 0x02, 0xf5, 0xa8, 0x5e, 0x24, 0x66, 0xea, 0x4f, 0x89, 0x2b, 0xd3,
0xa9, 0xd4, 0x21, 0x2f, 0x63, 0x46, 0x25, 0xf2, 0xa5, 0x60, 0x56, 0x9d, 0xa2, 0xcf, 0x18, 0x7b,
0x05, 0x53, 0xac, 0x4a, 0x9f, 0x1a, 0xfd, 0x1d, 0x51, 0x9a, 0x4a, 0xb6, 0x0e, 0x7b, 0x15, 0x73,
0x2e, 0xb1, 0x5f, 0x0e, 0xe4, 0xdd, 0x20, 0x79, 0xc6, 0xd0, 0xf7, 0x30, 0x09, 0x2b, 0xe4, 0xa9,
0x91, 0x69, 0xc9, 0xfc, 0xe9, 0xd8, 0xe1, 0xde, 0xc7, 0xac, 0xcc, 0x4b, 0xe6, 0xcb, 0xcc, 0xea,
0xb8, 0x81, 0xfc, 0xec, 0x70, 0xeb, 0x98, 0xa6, 0x79, 0x5c, 0x7f, 0xaa, 0x66, 0xf2, 0xe7, 0x91,
0xbc, 0x37, 0x7b, 0xc6, 0x3f, 0x8a, 0x63, 0x82, 0x65, 0xf6, 0xde, 0xac, 0x29, 0xbb, 0xec, 0x19,
0x53, 0xfe, 0x31, 0xb2, 0x75, 0x85, 0x3d, 0x35, 0xe7, 0x47, 0xc2, 0xad, 0x38, 0x3a, 0x23, 0xfb,
0x64, 0x58, 0xda, 0x80, 0xa3, 0x9d, 0x30, 0x6e, 0x4c, 0x55, 0x3f, 0xce, 0x21, 0x6f, 0x13, 0x51,
0xa6, 0x9f, 0x24, 0xad, 0x48, 0xbb, 0xd2, 0xca, 0x2e, 0x8c, 0x3b, 0xdb, 0x8a, 0x44, 0xb9, 0x56,
0x14, 0x12, 0x5a, 0x71, 0x82, 0xbe, 0xb4, 0xf2, 0x01, 0x6c, 0xaa, 0x59, 0x56, 0x9c, 0x14, 0xc0,
0x56, 0x7c, 0xa4, 0xc5, 0x65, 0xaf, 0xde, 0xa2, 0x7e, 0xfd, 0xb3, 0xc1, 0x02, 0x6c, 0x93, 0xce,
0xcf, 0xfe, 0x4a, 0x4b, 0xd2, 0x14, 0xe7, 0xa6, 0x69, 0x3f, 0x1d, 0x42, 0xf3, 0x79, 0x33, 0x4d,
0xfb, 0x99, 0x19, 0xb4, 0xf2, 0x6f, 0x68, 0x50, 0x6c, 0x42, 0x3d, 0xa9, 0x67, 0x44, 0xe2, 0xbd,
0xc6, 0xd6, 0xa3, 0xe2, 0x4b, 0xf8, 0x6b, 0xad, 0xd1, 0x78, 0x5c, 0xd4, 0xf4, 0xac, 0x48, 0xae,
0x7d, 0x79, 0x7f, 0x7d, 0xaf, 0x18, 0xd3, 0x0b, 0x22, 0xb7, 0xb1, 0xb5, 0xb3, 0xb9, 0x6e, 0xee,
0x9a, 0x5b, 0x3b, 0xfb, 0xc5, 0x38, 0xf6, 0x6d, 0x3c, 0x6e, 0x3c, 0xd8, 0x2f, 0x26, 0xf4, 0xb4,
0x88, 0x63, 0x5b, 0x52, 0x17, 0x22, 0xb5, 0xb7, 0x0f, 0xfd, 0x9b, 0xc5, 0x14, 0x5a, 0xd9, 0xdf,
0xda, 0x5e, 0x2f, 0xa6, 0x11, 0xb9, 0xff, 0xee, 0xee, 0xe3, 0xf5, 0x62, 0x06, 0x7f, 0x3e, 0x30,
0xcd, 0x07, 0x5f, 0x2e, 0x66, 0x91, 0xb4, 0xfd, 0x60, 0xb7, 0x28, 0xa8, 0xfb, 0xc1, 0x1a, 0x74,
0xe7, 0xf4, 0xbc, 0xc8, 0x6c, 0xbc, 0xbb, 0xf3, 0x70, 0x7f, 0xab, 0xb1, 0x53, 0xcc, 0x97, 0x7f,
0x33, 0x26, 0xc4, 0xa6, 0xbd, 0xf7, 0xa4, 0x3b, 0xa4, 0xaa, 0xf8, 0xba, 0x10, 0x63, 0xf8, 0xdd,
0x24, 0xe9, 0x71, 0x65, 0x97, 0xc5, 0x16, 0x0a, 0x3a, 0xfa, 0xab, 0x22, 0x4f, 0xdd, 0x6d, 0x19,
0x0a, 0xa8, 0xa0, 0x4b, 0x9b, 0x39, 0x6c, 0xe3, 0xe8, 0xe0, 0x87, 0xac, 0xd4, 0xa8, 0x8e, 0x4b,
0x29, 0x90, 0x95, 0x1a, 0xd4, 0xf7, 0xf4, 0xd8, 0x1c, 0x53, 0x58, 0xa7, 0xda, 0x2d, 0x6b, 0xd2,
0xb8, 0x32, 0xd0, 0x83, 0xc8, 0x69, 0x4c, 0x29, 0x8b, 0xc2, 0xb4, 0x44, 0x1d, 0x77, 0x97, 0xf0,
0x87, 0x94, 0x85, 0x47, 0x58, 0x6c, 0x88, 0xac, 0xdb, 0x8e, 0x63, 0x51, 0x2b, 0xcf, 0xa8, 0x48,
0x33, 0x12, 0xd4, 0xe4, 0x4e, 0x49, 0x02, 0xd8, 0x9b, 0x05, 0xf2, 0x46, 0x92, 0xa4, 0x3b, 0xe5,
0xeb, 0x62, 0x6e, 0xc7, 0x1e, 0xc8, 0x2d, 0x44, 0xab, 0x94, 0x17, 0x5a, 0xab, 0xa4, 0x51, 0x09,
0xa3, 0xb5, 0xca, 0x37, 0x84, 0x50, 0xfa, 0x8a, 0x42, 0x3b, 0x90, 0x7d, 0xb4, 0x11, 0xb5, 0x83,
0xf2, 0x9b, 0x22, 0xb5, 0xdd, 0x7a, 0xbe, 0xdf, 0xea, 0xc0, 0x58, 0xa2, 0xd7, 0x1a, 0x4f, 0x60,
0x6d, 0x50, 0x2a, 0xff, 0x0f, 0xff, 0x34, 0x3a, 0x71, 0x65, 0xb1, 0x55, 0x4a, 0xe5, 0xa9, 0x10,
0x8d, 0xde, 0xd1, 0xb6, 0x35, 0x1e, 0xb7, 0x3a, 0x16, 0x9c, 0x17, 0x52, 0x03, 0x30, 0x6a, 0xe1,
0x35, 0x05, 0x16, 0xf3, 0x57, 0xbd, 0x55, 0xf0, 0x50, 0x4b, 0x3b, 0x04, 0x31, 0x19, 0x0a, 0x1e,
0xc4, 0x07, 0x27, 0x7d, 0xba, 0xac, 0x48, 0x9a, 0xf8, 0x73, 0xf1, 0x9a, 0x48, 0x49, 0x0c, 0x5e,
0x8a, 0x0c, 0x5a, 0x7d, 0xab, 0x24, 0xc7, 0xa5, 0xdf, 0xe5, 0x5f, 0xd1, 0x84, 0xd8, 0xb1, 0x9e,
0x9d, 0x63, 0x4c, 0x0f, 0x15, 0x31, 0x66, 0x5c, 0x8e, 0xf9, 0x4e, 0xd4, 0x98, 0xa8, 0xb3, 0xb6,
0x6d, 0x1f, 0x35, 0xe5, 0x2b, 0x96, 0xf7, 0x2a, 0x59, 0x6c, 0xa1, 0xb7, 0x56, 0xfe, 0x40, 0xe4,
0xb7, 0x06, 0x03, 0x6b, 0xe4, 0xf8, 0x04, 0x26, 0x8e, 0xed, 0xf1, 0x84, 0x2f, 0x78, 0xe8, 0xb7,
0x5e, 0x12, 0x89, 0xa1, 0x3d, 0x9a, 0xc8, 0x79, 0xd6, 0x13, 0x70, 0xa6, 0xb9, 0x6b, 0x52, 0x8b,
0x7e, 0x4d, 0x64, 0x0f, 0x6d, 0xa0, 0x1f, 0xe2, 0x24, 0xe2, 0x54, 0x5b, 0x78, 0x0d, 0xe5, 0x5f,
0xd2, 0x44, 0xbe, 0x31, 0x39, 0xf6, 0x8c, 0x83, 0xef, 0x4f, 0xac, 0x53, 0x72, 0x0f, 0x7c, 0x87,
0x9f, 0x78, 0xb5, 0xf3, 0xb3, 0xad, 0xde, 0x89, 0xbc, 0xf0, 0xc9, 0x9b, 0xf2, 0x41, 0xbf, 0x24,
0x52, 0xcf, 0xac, 0x6e, 0xe7, 0x78, 0x42, 0x36, 0x63, 0x26, 0x3f, 0x41, 0x99, 0x90, 0xec, 0xa2,
0xb3, 0xa5, 0x04, 0xad, 0xd7, 0x25, 0x6f, 0xbd, 0xd4, 0x39, 0x98, 0x12, 0x74, 0x27, 0x93, 0x39,
0x2a, 0xfe, 0x02, 0xfc, 0x8b, 0x95, 0xdb, 0xe2, 0xa2, 0x13, 0x3b, 0x7c, 0x93, 0xdd, 0x11, 0xa5,
0x9e, 0x65, 0x83, 0x48, 0x20, 0xca, 0xf4, 0x4e, 0x9b, 0xcf, 0xec, 0x41, 0xb3, 0x35, 0x68, 0xda,
0xe3, 0xc3, 0xd6, 0x88, 0x16, 0x20, 0x7c, 0x88, 0x8b, 0xc0, 0xdb, 0x90, 0xb4, 0xf7, 0xed, 0xc1,
0x83, 0x41, 0x03, 0x39, 0xe5, 0xdf, 0x4f, 0x88, 0xec, 0xf6, 0xa9, 0x63, 0x1d, 0xe6, 0x76, 0x68,
0x9f, 0x0c, 0xe4, 0x5a, 0x26, 0x4d, 0xf9, 0xe0, 0xbe, 0xa3, 0x98, 0xf2, 0x8e, 0x00, 0xf9, 0xf4,
0xc4, 0x9e, 0x58, 0x34, 0xdd, 0xac, 0x29, 0x1f, 0x70, 0xb5, 0x86, 0xd6, 0x04, 0xe6, 0x8a, 0x15,
0x26, 0xfe, 0xf4, 0xe6, 0x9f, 0x3c, 0xc7, 0xfc, 0xe1, 0x9c, 0x9d, 0xb2, 0x71, 0xf5, 0xc7, 0xa5,
0x14, 0x5d, 0x6e, 0x29, 0x70, 0xf5, 0xad, 0x98, 0x8c, 0xd2, 0xb7, 0xc4, 0xc2, 0x33, 0xab, 0xd9,
0x3f, 0x81, 0x6d, 0xd3, 0xb1, 0xe1, 0x0c, 0x06, 0x51, 0x7b, 0x04, 0x41, 0x05, 0x47, 0x52, 0x62,
0xc2, 0xac, 0x85, 0x34, 0xe7, 0x9f, 0x59, 0xdb, 0xc0, 0xdb, 0xb4, 0x1f, 0x11, 0x0b, 0x94, 0x9d,
0x85, 0x14, 0xd4, 0x94, 0xce, 0xe6, 0x83, 0xa3, 0xfb, 0xa8, 0x19, 0x00, 0x52, 0x83, 0xbe, 0x2c,
0x32, 0x07, 0xdd, 0x27, 0xd6, 0xf8, 0x18, 0xb4, 0x94, 0x86, 0x61, 0xe7, 0x8d, 0x2b, 0x1e, 0xc7,
0x5d, 0xd6, 0xa5, 0x87, 0x76, 0xcf, 0x1e, 0x99, 0x2e, 0x14, 0x8e, 0x08, 0xd9, 0xb1, 0xdd, 0xb7,
0xa4, 0xbe, 0x33, 0x94, 0xd9, 0xae, 0xcf, 0xe2, 0xed, 0x01, 0xc8, 0x89, 0x60, 0x0e, 0x5e, 0xbf,
0x2a, 0x1d, 0x3d, 0xc0, 0xf3, 0x6b, 0x49, 0x50, 0x7d, 0x8e, 0x0e, 0xd1, 0x79, 0x56, 0x5f, 0x44,
0x87, 0x3a, 0x6d, 0x3c, 0x96, 0x40, 0x80, 0xc6, 0xe2, 0xce, 0x7d, 0x5e, 0x7c, 0x0b, 0x42, 0x9f,
0x63, 0xd0, 0x0b, 0x7d, 0x32, 0xdc, 0x64, 0x29, 0x1e, 0xc8, 0xd0, 0x27, 0x63, 0xcd, 0x6b, 0x22,
0x49, 0x6e, 0x63, 0x9a, 0x30, 0xd7, 0x31, 0x2b, 0x41, 0x9a, 0xd8, 0x34, 0xd7, 0xd7, 0x77, 0x20,
0x2d, 0x61, 0x82, 0x7a, 0xfc, 0xee, 0x7a, 0x31, 0xa6, 0x28, 0xf6, 0xb7, 0x34, 0x11, 0x5f, 0x7f,
0x4e, 0x6a, 0xc1, 0x69, 0x38, 0x3b, 0x1a, 0x7f, 0x1b, 0x2b, 0x22, 0xd1, 0xb7, 0x47, 0x96, 0x7e,
0x61, 0xc6, 0x2c, 0x4b, 0x1d, 0x7a, 0x5f, 0xca, 0x55, 0x2e, 0x58, 0x31, 0x09, 0x6f, 0xbc, 0x21,
0x12, 0x13, 0x0b, 0x6c, 0xce, 0xe4, 0x1d, 0xcb, 0x01, 0x10, 0x60, 0x40, 0x18, 0x85, 0xb8, 0x72,
0x00, 0xaf, 0x64, 0x26, 0xb4, 0x4b, 0xd3, 0x63, 0x48, 0xf9, 0x3d, 0x51, 0x7c, 0x68, 0xf7, 0x87,
0x3d, 0xeb, 0x39, 0x8c, 0x64, 0x0d, 0xc6, 0x90, 0xb2, 0x51, 0xcf, 0xed, 0xee, 0x88, 0xa2, 0x08,
0x5d, 0xd8, 0xd2, 0x03, 0xee, 0xea, 0xb1, 0x05, 0xd1, 0xe1, 0x88, 0x03, 0x26, 0x3f, 0x21, 0x7a,
0x72, 0xdc, 0x1d, 0x61, 0x00, 0xc1, 0x38, 0x2f, 0x1f, 0xca, 0x9b, 0xa2, 0xc0, 0x07, 0xfd, 0x31,
0x0f, 0x5c, 0xbe, 0x23, 0xf2, 0x4e, 0x13, 0xdd, 0x5e, 0xc3, 0xc2, 0x7d, 0xb0, 0x6e, 0x36, 0x60,
0x35, 0x61, 0x59, 0x1b, 0x3b, 0xeb, 0xb0, 0x96, 0xf0, 0x63, 0xff, 0xfd, 0x86, 0x6f, 0x29, 0xaf,
0x89, 0xbc, 0xeb, 0xfb, 0x9e, 0x35, 0xa1, 0x1e, 0x4c, 0x08, 0xe9, 0x7a, 0x2c, 0xa3, 0x95, 0xd3,
0x22, 0xb9, 0xde, 0x1f, 0x4e, 0x4e, 0xcb, 0x3f, 0x2f, 0x72, 0x0c, 0x7a, 0xdc, 0x05, 0x67, 0x57,
0x45, 0xba, 0xcf, 0xf3, 0xd5, 0xe8, 0xcc, 0xa5, 0x6a, 0xca, 0xc3, 0x39, 0xbf, 0x4d, 0x07, 0xbd,
0x58, 0x15, 0x69, 0x25, 0x96, 0xf2, 0x56, 0x8f, 0xa9, 0x5b, 0x5d, 0x06, 0x85, 0xb8, 0x12, 0x14,
0xca, 0xdb, 0x22, 0x2d, 0x33, 0xe0, 0x98, 0xb2, 0xba, 0xac, 0xd7, 0xa4, 0x98, 0xe4, 0x9b, 0xcf,
0xc9, 0x36, 0x79, 0x85, 0x0c, 0x72, 0x23, 0xc1, 0x32, 0x42, 0x86, 0x4e, 0x41, 0x4d, 0x52, 0x6e,
0xbf, 0x97, 0x14, 0x19, 0x67, 0xa5, 0x40, 0xe2, 0x29, 0x59, 0x24, 0x91, 0x29, 0xa7, 0x88, 0x4f,
0x52, 0x59, 0x04, 0x9d, 0x69, 0x2e, 0x84, 0x38, 0xba, 0x63, 0xc5, 0x9e, 0x92, 0x85, 0x8f, 0xdb,
0x09, 0x67, 0x8b, 0xb8, 0x5b, 0x9e, 0xa7, 0x64, 0x69, 0xa3, 0xdf, 0x14, 0x59, 0xb7, 0x98, 0xa1,
0x78, 0xcc, 0xb5, 0x78, 0xc6, 0xa9, 0x5e, 0x14, 0x04, 0x18, 0x48, 0x7a, 0x85, 0x77, 0xa6, 0xed,
0x1d, 0x4f, 0x32, 0x4e, 0x49, 0x42, 0x77, 0xe8, 0x4e, 0x95, 0x9d, 0xe6, 0x22, 0xc4, 0x03, 0x80,
0x85, 0xb4, 0x52, 0x52, 0xa7, 0xb9, 0xd0, 0x00, 0x40, 0x9a, 0x4b, 0x0b, 0xda, 0xfa, 0x5e, 0xfd,
0x9c, 0x92, 0xe5, 0x04, 0x2c, 0x67, 0xc6, 0x29, 0x20, 0x68, 0x5f, 0x7a, 0xc5, 0x72, 0x9a, 0x8b,
0x06, 0xfd, 0x4d, 0x84, 0xc8, 0xe5, 0x87, 0x10, 0x30, 0xbb, 0x32, 0x4e, 0x73, 0x65, 0x0c, 0x93,
0x4a, 0x73, 0x41, 0x4c, 0x21, 0x41, 0xa9, 0x82, 0x53, 0xb2, 0x0a, 0xd6, 0x6f, 0x90, 0x39, 0x39,
0xa9, 0xbc, 0x57, 0xf1, 0xa6, 0xb9, 0xca, 0xf0, 0xfa, 0xe9, 0xc8, 0xe6, 0x56, 0xb7, 0x69, 0xae,
0x23, 0xf4, 0x15, 0x7c, 0x5f, 0xa8, 0x6f, 0x38, 0xae, 0x61, 0x10, 0x2c, 0x79, 0xc2, 0x73, 0xde,
0xa9, 0x8c, 0x81, 0x75, 0x19, 0x41, 0xe0, 0x55, 0xd2, 0x6e, 0x58, 0x44, 0xde, 0x6e, 0x77, 0xd0,
0x86, 0x73, 0x1c, 0xae, 0x44, 0x1c, 0x7e, 0x42, 0x1f, 0xb6, 0x48, 0x0d, 0xec, 0x60, 0x5f, 0x91,
0xfa, 0x12, 0x6f, 0xcb, 0x4e, 0x6c, 0x82, 0xf4, 0x9e, 0x84, 0xce, 0xd6, 0x00, 0x0e, 0x64, 0xc4,
0x1b, 0xb4, 0x06, 0x66, 0xa2, 0x0d, 0x0d, 0xfa, 0x1b, 0x22, 0x3e, 0x3e, 0x39, 0x28, 0xe9, 0xc1,
0xcf, 0x1b, 0x7b, 0x27, 0x07, 0x8e, 0x2b, 0x26, 0x22, 0xc0, 0x7e, 0x06, 0x04, 0xda, 0xfc, 0x39,
0x6b, 0x64, 0x97, 0x2e, 0xd0, 0x12, 0xbe, 0x64, 0xa6, 0xa1, 0xe5, 0x03, 0x68, 0x38, 0x67, 0xf0,
0x83, 0xc3, 0x5d, 0x4e, 0xb1, 0x0b, 0x27, 0x74, 0x6d, 0x20, 0x4f, 0x0a, 0x75, 0x6d, 0xd5, 0xd4,
0x06, 0xe5, 0x7d, 0x91, 0x77, 0x0a, 0x09, 0x9a, 0xaf, 0x81, 0x3b, 0x09, 0xcc, 0xd2, 0xfe, 0x9c,
0x37, 0xae, 0xa9, 0x29, 0xca, 0x83, 0x71, 0xba, 0x90, 0xd0, 0x72, 0x31, 0xe0, 0x8a, 0x56, 0xfe,
0x01, 0x9c, 0x51, 0xb6, 0x21, 0x3a, 0xba, 0x97, 0xa6, 0xb0, 0x41, 0x0f, 0x60, 0x67, 0x8c, 0xc9,
0x6c, 0xc6, 0x94, 0x0f, 0xfa, 0x6b, 0x22, 0x4f, 0x3f, 0x9c, 0x02, 0x30, 0xe6, 0xde, 0x2f, 0xe4,
0xa8, 0x9d, 0xab, 0x3e, 0xd8, 0xf1, 0xf0, 0x12, 0xc7, 0x1c, 0xc9, 0xe8, 0xb7, 0xfe, 0x19, 0x91,
0xc3, 0xbf, 0x0e, 0x33, 0xe1, 0x1e, 0x58, 0x05, 0x36, 0x33, 0xf1, 0x0d, 0x31, 0x47, 0x6f, 0xdf,
0x85, 0xa5, 0xdd, 0xbb, 0x84, 0xbc, 0xec, 0x60, 0x60, 0x49, 0xa4, 0x65, 0x28, 0x18, 0xd3, 0x27,
0xab, 0xac, 0xe9, 0x3c, 0x62, 0x78, 0xa5, 0x4a, 0x40, 0xa6, 0xfb, 0xb4, 0xc9, 0x4f, 0xe5, 0x07,
0x22, 0x43, 0x59, 0x0a, 0x8e, 0xb1, 0x7a, 0x59, 0x68, 0x9d, 0x92, 0x45, 0x39, 0xf2, 0xa2, 0x72,
0xcc, 0xe7, 0xee, 0xa5, 0x4d, 0x53, 0xeb, 0x2c, 0x2e, 0x08, 0x6d, 0x13, 0xcf, 0xdd, 0xcf, 0x39,
0x4c, 0x6b, 0xcf, 0xcb, 0x0d, 0x36, 0x01, 0xa7, 0xd2, 0x28, 0x13, 0xd0, 0x2d, 0x4d, 0xbc, 0x32,
0x65, 0x02, 0x9f, 0x4e, 0xf9, 0xfb, 0x9d, 0x76, 0x5a, 0xae, 0x8a, 0x39, 0xda, 0x9e, 0xe0, 0xf8,
0xae, 0x0d, 0xf3, 0xc3, 0xee, 0x36, 0x9d, 0x93, 0xe0, 0x1c, 0xdf, 0xc6, 0x77, 0x60, 0x3d, 0x6f,
0x1d, 0xca, 0x13, 0x27, 0xbc, 0x03, 0x7a, 0x28, 0x7f, 0x9a, 0x10, 0xf3, 0x1c, 0x5a, 0xdf, 0xef,
0x4e, 0x8e, 0xb7, 0x5b, 0x43, 0xfd, 0xb1, 0xc8, 0x63, 0x54, 0x6d, 0xf6, 0x5b, 0xc3, 0x21, 0x6e,
0x5f, 0x8d, 0x8e, 0x1a, 0xb7, 0xa7, 0x42, 0x35, 0xe3, 0x97, 0x76, 0x00, 0xbc, 0x2d, 0xb1, 0xeb,
0x83, 0xc9, 0xe8, 0xd4, 0xcc, 0x0d, 0xbc, 0x16, 0x38, 0x00, 0xe5, 0xfa, 0xe3, 0x8e, 0x6b, 0x2c,
0x46, 0xc6, 0x6e, 0x85, 0x1a, 0xdb, 0x1e, 0x77, 0x7c, 0xb6, 0x44, 0xdf, 0x6d, 0x40, 0xc7, 0x30,
0x1e, 0xbb, 0xb6, 0xe2, 0x67, 0x38, 0x86, 0xa1, 0xc3, 0xef, 0xd8, 0x81, 0xd7, 0x02, 0x05, 0xbc,
0xc0, 0xed, 0x35, 0xb1, 0xb1, 0x74, 0x22, 0x05, 0xe5, 0x8c, 0xd7, 0x43, 0x6d, 0x41, 0xa4, 0xda,
0xb7, 0xe1, 0x3f, 0xd2, 0x10, 0x6e, 0x4c, 0x7a, 0x5c, 0xfc, 0x82, 0x28, 0x06, 0xe7, 0xaf, 0x9e,
0xc8, 0x93, 0x33, 0x4e, 0xe4, 0x59, 0x3e, 0x91, 0xd7, 0x63, 0xf7, 0xb4, 0xc5, 0xf7, 0x44, 0x21,
0x30, 0x65, 0x95, 0xae, 0x4b, 0xfa, 0xdb, 0x2a, 0x3d, 0x67, 0x5c, 0x56, 0xbe, 0x29, 0xab, 0x2f,
0x5c, 0xb5, 0x0b, 0x7e, 0x05, 0xa7, 0xaf, 0x1a, 0xce, 0x44, 0x54, 0x0a, 0xc4, 0x7f, 0x47, 0xcc,
0xf9, 0xa6, 0xac, 0x92, 0xb3, 0x67, 0x4c, 0xaa, 0xfc, 0x8b, 0x49, 0x91, 0x6c, 0x0c, 0x2c, 0xbb,
0xad, 0x5f, 0xf6, 0xe7, 0xc9, 0x2f, 0xbe, 0xe4, 0xe4, 0xc8, 0x2b, 0x81, 0x1c, 0x09, 0x3d, 0x4e,
0x86, 0xbc, 0x12, 0xc8, 0x90, 0x4e, 0x17, 0x84, 0xf1, 0xeb, 0x53, 0xf9, 0x11, 0x3a, 0xbd, 0xe4,
0x78, 0x7d, 0x2a, 0x39, 0x7a, 0xdd, 0xc0, 0xbe, 0x1a, 0xcc, 0x8c, 0xd0, 0xeb, 0x66, 0xc5, 0xab,
0xc1, 0xac, 0xe8, 0x76, 0x02, 0xf3, 0x4a, 0x20, 0x23, 0x92, 0x4b, 0x32, 0x17, 0x5e, 0x0d, 0xe6,
0x42, 0xe2, 0x71, 0x16, 0xbc, 0x1a, 0xcc, 0x82, 0xd4, 0xc9, 0x59, 0xef, 0x4a, 0x20, 0xeb, 0x91,
0x51, 0x99, 0xee, 0xae, 0x06, 0xd3, 0x9d, 0xe4, 0x29, 0x9e, 0xaa, 0xb9, 0xce, 0xed, 0x04, 0x4f,
0x8d, 0x40, 0xa2, 0x0b, 0x3f, 0xed, 0xd3, 0xbb, 0xa0, 0xa0, 0x5f, 0xc3, 0x65, 0x73, 0x0e, 0xa2,
0x85, 0x88, 0xcf, 0xee, 0xb4, 0x9a, 0xce, 0x41, 0xcc, 0x10, 0xe9, 0x36, 0x17, 0xc0, 0x45, 0x8a,
0x5c, 0x8a, 0x2c, 0xe9, 0xe5, 0x2f, 0x6d, 0x34, 0x29, 0x82, 0xd1, 0xbc, 0xe4, 0x99, 0xfe, 0x16,
0x84, 0xa8, 0xe6, 0xe3, 0xd6, 0xa8, 0x03, 0xc0, 0xe6, 0x7e, 0xab, 0xe3, 0x5e, 0x22, 0xe0, 0xfb,
0xcf, 0xb5, 0xb9, 0x07, 0xef, 0x1a, 0x2e, 0x39, 0xe2, 0x3a, 0xa2, 0x5e, 0x8d, 0xe5, 0xb5, 0x78,
0x19, 0x17, 0x4d, 0x1a, 0xa3, 0x58, 0xb8, 0xc0, 0xb1, 0x70, 0x0d, 0xce, 0x9c, 0x27, 0x03, 0x38,
0x27, 0xaf, 0x65, 0x45, 0x7a, 0x62, 0x8f, 0xfa, 0xad, 0x89, 0x5d, 0xfe, 0xa1, 0x26, 0x04, 0x9c,
0xa3, 0xfb, 0xd0, 0xf1, 0x14, 0x2a, 0x60, 0x48, 0x86, 0xfd, 0xd6, 0x13, 0x88, 0x1f, 0x56, 0xf3,
0x70, 0xe4, 0xec, 0x83, 0x2c, 0x36, 0x6d, 0x5b, 0x0f, 0x41, 0xe2, 0x25, 0xe7, 0x88, 0x4e, 0xda,
0x21, 0x49, 0xf2, 0x91, 0xfd, 0x22, 0x1f, 0x3a, 0x53, 0xfc, 0x0e, 0x9d, 0x63, 0xa7, 0xac, 0x23,
0xd2, 0xfc, 0xf6, 0xe8, 0x09, 0x25, 0x3f, 0xb1, 0xfa, 0xc3, 0xe6, 0x21, 0x49, 0x05, 0xe5, 0x90,
0xc4, 0xe7, 0x87, 0xb0, 0x8b, 0xe3, 0x90, 0x30, 0x49, 0x24, 0x67, 0xbc, 0x17, 0xc4, 0x41, 0x76,
0x8c, 0x43, 0xec, 0x23, 0xd9, 0xe4, 0x8c, 0x05, 0xe5, 0x9c, 0x20, 0x53, 0x13, 0xc2, 0xa0, 0xdf,
0x9d, 0xf7, 0x9d, 0x82, 0x88, 0x6f, 0x34, 0x1a, 0x98, 0xfb, 0xe1, 0x4f, 0xa5, 0xa8, 0xd5, 0x3f,
0x27, 0x32, 0x9d, 0x91, 0x65, 0x61, 0x78, 0x98, 0x5d, 0x73, 0x7c, 0x48, 0xb9, 0xce, 0x05, 0xd5,
0xe1, 0xc0, 0x7c, 0x28, 0xab, 0x0e, 0x3d, 0xa4, 0xac, 0x2d, 0xfd, 0x81, 0xbc, 0x54, 0x59, 0xf4,
0xba, 0x83, 0x75, 0x8a, 0xe9, 0xd8, 0xa8, 0xef, 0x42, 0x19, 0xd8, 0x3c, 0xcb, 0xe0, 0x47, 0x32,
0xbb, 0x44, 0x19, 0xcc, 0x8c, 0xb8, 0xa9, 0xbe, 0x2e, 0x16, 0x06, 0xb6, 0xf3, 0x21, 0xa3, 0x79,
0x24, 0xf7, 0xd8, 0x95, 0xe9, 0xa3, 0x9c, 0x63, 0xdc, 0x92, 0x1f, 0x0f, 0x07, 0x36, 0x77, 0xc8,
0x5d, 0x59, 0x7f, 0x28, 0x8a, 0x8a, 0x19, 0x2a, 0x3d, 0xa3, 0xac, 0xb4, 0xe5, 0xd7, 0x4a, 0xd7,
0x0a, 0xed, 0xfb, 0x80, 0x11, 0xb9, 0x33, 0x23, 0x8c, 0x74, 0xe4, 0xa7, 0x5f, 0xd7, 0x08, 0x85,
0xba, 0x69, 0x23, 0x18, 0x6b, 0xc2, 0x8d, 0x1c, 0xcb, 0xaf, 0xc2, 0xaa, 0x91, 0x95, 0x5a, 0x60,
0x55, 0x4e, 0xce, 0x74, 0xa5, 0x2b, 0x3f, 0xea, 0xba, 0x56, 0x64, 0x00, 0x9c, 0x61, 0x26, 0xda,
0x99, 0x0f, 0xe5, 0xf7, 0x5e, 0x9f, 0x99, 0x29, 0x6f, 0xc6, 0x67, 0x7a, 0xf3, 0x44, 0x7e, 0x5c,
0x75, 0xcd, 0xec, 0xcd, 0xf2, 0x66, 0x7c, 0xa6, 0x37, 0x3d, 0xf9, 0xd9, 0xd5, 0x67, 0x06, 0xbc,
0xd9, 0x14, 0xba, 0xfa, 0xaa, 0x39, 0x4f, 0x44, 0xd8, 0xe9, 0xcb, 0x8f, 0xe9, 0xde, 0xcb, 0x96,
0x94, 0x59, 0x86, 0xa2, 0x1d, 0x1a, 0xc8, 0xef, 0xec, 0x7e, 0x43, 0xe0, 0xd1, 0x96, 0xb8, 0xa0,
0x4e, 0xec, 0x1c, 0x2e, 0xd9, 0x60, 0xa9, 0x60, 0x2e, 0x78, 0x53, 0x63, 0xce, 0x4c, 0x53, 0xd1,
0x4e, 0x0d, 0xc1, 0x54, 0x71, 0xca, 0x14, 0x78, 0xf5, 0x40, 0x14, 0x14, 0x53, 0x07, 0x94, 0xa1,
0xc3, 0xcd, 0x3c, 0x95, 0xff, 0xc3, 0x83, 0x6b, 0x06, 0x33, 0x7a, 0xf0, 0x8d, 0x71, 0x8e, 0x0b,
0x37, 0x32, 0x92, 0x5f, 0xeb, 0x3d, 0x5f, 0x88, 0x11, 0xd8, 0x12, 0x54, 0x7f, 0x47, 0x59, 0x19,
0xcb, 0xef, 0xf8, 0x9e, 0x2b, 0x48, 0xa8, 0x77, 0x7d, 0xd3, 0xb1, 0x30, 0xc9, 0x45, 0xd8, 0x98,
0x50, 0x44, 0x7e, 0x3d, 0x14, 0xb0, 0xa4, 0x5e, 0x90, 0x28, 0xd3, 0xc6, 0x47, 0x78, 0x09, 0xf3,
0xe7, 0x0f, 0x48, 0x1f, 0x69, 0xb2, 0x5a, 0xae, 0x2e, 0x61, 0x41, 0x6d, 0xce, 0x1d, 0xf9, 0xe2,
0xd2, 0xba, 0x98, 0x3b, 0x77, 0x50, 0xfa, 0x58, 0x93, 0x35, 0x27, 0x5a, 0x32, 0xf3, 0x47, 0xfe,
0xc8, 0x34, 0x77, 0xee, 0xb0, 0xf4, 0x89, 0x26, 0x2f, 0x28, 0x6a, 0x86, 0x6b, 0xc4, 0x89, 0x4c,
0x73, 0xe7, 0x0e, 0x4b, 0x5f, 0x91, 0x15, 0x65, 0xac, 0x56, 0x55, 0x8d, 0x50, 0x2c, 0x98, 0x3f,
0x7f, 0x58, 0xfa, 0xaa, 0x46, 0x97, 0x15, 0xb1, 0x5a, 0xcd, 0x5d, 0x17, 0x37, 0x32, 0xcd, 0x9f,
0x3f, 0x2c, 0x7d, 0x4d, 0xa3, 0x2b, 0x8d, 0x58, 0x6d, 0xd9, 0x67, 0xc6, 0xef, 0xcd, 0xd9, 0x61,
0xe9, 0xeb, 0x1a, 0xdd, 0x32, 0xc4, 0x6a, 0x2b, 0xae, 0x99, 0xbd, 0x29, 0x6f, 0xce, 0x0e, 0x4b,
0xdf, 0xa0, 0x53, 0x3c, 0x98, 0x59, 0xf5, 0x99, 0xa1, 0xc8, 0x54, 0x78, 0x81, 0xb0, 0xf4, 0x4d,
0x8d, 0x2e, 0x83, 0x62, 0xb5, 0x7b, 0xa6, 0x33, 0xba, 0x17, 0x99, 0x0a, 0x2f, 0x10, 0x96, 0x3e,
0xd5, 0xe8, 0xce, 0x28, 0x56, 0xbb, 0xef, 0x37, 0x44, 0x91, 0xa9, 0xf8, 0x22, 0x61, 0xe9, 0x5b,
0x68, 0xa9, 0x50, 0x8f, 0x2d, 0xdf, 0x35, 0x1d, 0x07, 0x94, 0xc8, 0x54, 0x7c, 0x91, 0xb0, 0xf4,
0x6d, 0x34, 0x55, 0x04, 0x53, 0x95, 0x80, 0x29, 0xf0, 0xea, 0xa1, 0xc8, 0x9f, 0x37, 0x2c, 0x7d,
0x47, 0xbd, 0x8b, 0xcb, 0x1d, 0x29, 0xb1, 0x69, 0x57, 0x79, 0x67, 0x67, 0x06, 0xa6, 0xef, 0x52,
0x8d, 0x53, 0x9f, 0xfb, 0xa2, 0xbc, 0xaf, 0x92, 0x04, 0xef, 0xf5, 0xc9, 0x30, 0xb5, 0xed, 0xed,
0x8f, 0x33, 0x63, 0xd4, 0xf7, 0x34, 0xba, 0xd4, 0xca, 0xb3, 0x41, 0xc2, 0xbb, 0x3b, 0x45, 0x06,
0xac, 0x0f, 0xbd, 0x59, 0x9e, 0x15, 0xad, 0xbe, 0xaf, 0xbd, 0x48, 0xb8, 0xaa, 0xe3, 0x1d, 0xae,
0xbb, 0x18, 0xd4, 0xf2, 0x79, 0x91, 0x78, 0x6e, 0xdc, 0xad, 0xa8, 0x47, 0x32, 0xf5, 0x2e, 0x57,
0x06, 0xa9, 0x9c, 0x51, 0x50, 0xae, 0xbb, 0xf1, 0x32, 0xd7, 0x24, 0x16, 0xb3, 0x8d, 0x50, 0xf6,
0xc7, 0x11, 0x6c, 0x83, 0xd9, 0xd5, 0x50, 0xf6, 0x27, 0x11, 0xec, 0x2a, 0xb3, 0x6b, 0xa1, 0xec,
0xaf, 0x44, 0xb0, 0x6b, 0xcc, 0x5e, 0x0e, 0x65, 0x7f, 0x35, 0x82, 0xbd, 0xcc, 0xec, 0x95, 0x50,
0xf6, 0xd7, 0x22, 0xd8, 0x2b, 0xcc, 0x5e, 0x0d, 0x65, 0x7f, 0x3d, 0x82, 0xbd, 0xca, 0xec, 0x7b,
0xa1, 0xec, 0x6f, 0x44, 0xb0, 0xef, 0x31, 0xfb, 0x7e, 0x28, 0xfb, 0x9b, 0x11, 0xec, 0xfb, 0x92,
0x5d, 0xb9, 0x1b, 0xca, 0xfe, 0x34, 0x9c, 0x5d, 0xb9, 0xcb, 0xec, 0x70, 0xad, 0x7d, 0x2b, 0x82,
0xcd, 0x5a, 0xab, 0x84, 0x6b, 0xed, 0xdb, 0x11, 0x6c, 0xd6, 0x5a, 0x25, 0x5c, 0x6b, 0xdf, 0x89,
0x60, 0xb3, 0xd6, 0x2a, 0xe1, 0x5a, 0xfb, 0x6e, 0x04, 0x9b, 0xb5, 0x56, 0x09, 0xd7, 0xda, 0xf7,
0x22, 0xd8, 0xac, 0xb5, 0x4a, 0xb8, 0xd6, 0xbe, 0x1f, 0xc1, 0x66, 0xad, 0x55, 0xc2, 0xb5, 0xf6,
0x87, 0x11, 0x6c, 0xd6, 0x5a, 0x25, 0x5c, 0x6b, 0x7f, 0x14, 0xc1, 0x66, 0xad, 0x55, 0xc2, 0xb5,
0xf6, 0xc7, 0x11, 0x6c, 0xd6, 0x9a, 0x11, 0xae, 0xb5, 0x3f, 0x09, 0x67, 0x1b, 0xac, 0x35, 0x23,
0x5c, 0x6b, 0x7f, 0x1a, 0xc1, 0x66, 0xad, 0x19, 0xe1, 0x5a, 0xfb, 0xb3, 0x08, 0x36, 0x6b, 0xcd,
0x08, 0xd7, 0xda, 0x0f, 0x22, 0xd8, 0xac, 0x35, 0x23, 0x5c, 0x6b, 0x7f, 0x1e, 0xc1, 0x66, 0xad,
0x19, 0xe1, 0x5a, 0xfb, 0x8b, 0x08, 0x36, 0x6b, 0xcd, 0x08, 0xd7, 0xda, 0x5f, 0x46, 0xb0, 0x59,
0x6b, 0x46, 0xb8, 0xd6, 0xfe, 0x2a, 0x82, 0xcd, 0x5a, 0x33, 0xc2, 0xb5, 0xf6, 0xd7, 0x11, 0x6c,
0xd6, 0x9a, 0x11, 0xae, 0xb5, 0xbf, 0x89, 0x60, 0xb3, 0xd6, 0xaa, 0xe1, 0x5a, 0xfb, 0xdb, 0x70,
0x76, 0x95, 0xb5, 0x56, 0x0d, 0xd7, 0xda, 0xdf, 0x45, 0xb0, 0x59, 0x6b, 0xd5, 0x70, 0xad, 0xfd,
0x7d, 0x04, 0x9b, 0xb5, 0x56, 0x0d, 0xd7, 0xda, 0x3f, 0x44, 0xb0, 0x59, 0x6b, 0xd5, 0x70, 0xad,
0xfd, 0x30, 0x82, 0xcd, 0x5a, 0xab, 0x86, 0x6b, 0xed, 0x1f, 0x23, 0xd8, 0xac, 0xb5, 0x6a, 0xb8,
0xd6, 0xfe, 0x29, 0x82, 0xcd, 0x5a, 0xab, 0x86, 0x6b, 0xed, 0x9f, 0x23, 0xd8, 0xac, 0xb5, 0x6a,
0xb8, 0xd6, 0xfe, 0x25, 0x82, 0xcd, 0x5a, 0xab, 0x86, 0x6b, 0xed, 0x5f, 0x23, 0xd8, 0xac, 0xb5,
0x5a, 0xb8, 0xd6, 0xfe, 0x2d, 0x9c, 0x5d, 0x63, 0xad, 0xd5, 0xc2, 0xb5, 0xf6, 0xef, 0x11, 0x6c,
0xd6, 0x5a, 0x2d, 0x5c, 0x6b, 0xff, 0x11, 0xc1, 0x66, 0xad, 0xd5, 0xc2, 0xb5, 0xf6, 0x9f, 0x11,
0x6c, 0xd6, 0x5a, 0x2d, 0x5c, 0x6b, 0xff, 0x15, 0xc1, 0x66, 0xad, 0xd5, 0xc2, 0xb5, 0xf6, 0xdf,
0x11, 0x6c, 0xd6, 0x5a, 0x2d, 0x5c, 0x6b, 0x3f, 0x8a, 0x60, 0xb3, 0xd6, 0x6a, 0xe1, 0x5a, 0xfb,
0x71, 0x04, 0x9b, 0xb5, 0x56, 0x0b, 0xd7, 0xda, 0xff, 0x44, 0xb0, 0x59, 0x6b, 0xb5, 0x70, 0xad,
0xfd, 0x6f, 0x04, 0x9b, 0xb5, 0xb6, 0x1c, 0xae, 0xb5, 0xff, 0x0b, 0x67, 0x2f, 0xdf, 0xfd, 0x49,
0x00, 0x00, 0x00, 0xff, 0xff, 0x0d, 0x56, 0x3d, 0xa6, 0xdc, 0x38, 0x00, 0x00,
}

View File

@ -488,6 +488,7 @@ message GroupNew {
message FloatingPoint {
required double f = 1;
optional bool exact = 2;
}
message MessageWithMap {

View File

@ -42,9 +42,7 @@ var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
const _ = proto.ProtoPackageIsVersion1
type FieldDescriptorProto_Type int32
@ -945,9 +943,9 @@ type FileOptions struct {
// Namespace for generated classes; defaults to the package.
CsharpNamespace *string `protobuf:"bytes,37,opt,name=csharp_namespace,json=csharpNamespace" json:"csharp_namespace,omitempty"`
// The parser stores options it doesn't recognize here. See above.
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *FileOptions) Reset() { *m = FileOptions{} }
@ -962,6 +960,12 @@ var extRange_FileOptions = []proto.ExtensionRange{
func (*FileOptions) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_FileOptions
}
func (m *FileOptions) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
const Default_FileOptions_JavaMultipleFiles bool = false
const Default_FileOptions_JavaGenerateEqualsAndHash bool = false
@ -1130,9 +1134,9 @@ type MessageOptions struct {
// parser.
MapEntry *bool `protobuf:"varint,7,opt,name=map_entry,json=mapEntry" json:"map_entry,omitempty"`
// The parser stores options it doesn't recognize here. See above.
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *MessageOptions) Reset() { *m = MessageOptions{} }
@ -1147,6 +1151,12 @@ var extRange_MessageOptions = []proto.ExtensionRange{
func (*MessageOptions) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_MessageOptions
}
func (m *MessageOptions) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
const Default_MessageOptions_MessageSetWireFormat bool = false
const Default_MessageOptions_NoStandardDescriptorAccessor bool = false
@ -1246,9 +1256,9 @@ type FieldOptions struct {
// For Google-internal migration only. Do not use.
Weak *bool `protobuf:"varint,10,opt,name=weak,def=0" json:"weak,omitempty"`
// The parser stores options it doesn't recognize here. See above.
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *FieldOptions) Reset() { *m = FieldOptions{} }
@ -1263,6 +1273,12 @@ var extRange_FieldOptions = []proto.ExtensionRange{
func (*FieldOptions) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_FieldOptions
}
func (m *FieldOptions) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
const Default_FieldOptions_Ctype FieldOptions_CType = FieldOptions_STRING
const Default_FieldOptions_Jstype FieldOptions_JSType = FieldOptions_JS_NORMAL
@ -1329,9 +1345,9 @@ type EnumOptions struct {
// is a formalization for deprecating enums.
Deprecated *bool `protobuf:"varint,3,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
// The parser stores options it doesn't recognize here. See above.
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *EnumOptions) Reset() { *m = EnumOptions{} }
@ -1346,6 +1362,12 @@ var extRange_EnumOptions = []proto.ExtensionRange{
func (*EnumOptions) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_EnumOptions
}
func (m *EnumOptions) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
const Default_EnumOptions_Deprecated bool = false
@ -1377,9 +1399,9 @@ type EnumValueOptions struct {
// this is a formalization for deprecating enum values.
Deprecated *bool `protobuf:"varint,1,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
// The parser stores options it doesn't recognize here. See above.
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *EnumValueOptions) Reset() { *m = EnumValueOptions{} }
@ -1394,6 +1416,12 @@ var extRange_EnumValueOptions = []proto.ExtensionRange{
func (*EnumValueOptions) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_EnumValueOptions
}
func (m *EnumValueOptions) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
const Default_EnumValueOptions_Deprecated bool = false
@ -1418,9 +1446,9 @@ type ServiceOptions struct {
// this is a formalization for deprecating services.
Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
// The parser stores options it doesn't recognize here. See above.
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *ServiceOptions) Reset() { *m = ServiceOptions{} }
@ -1435,6 +1463,12 @@ var extRange_ServiceOptions = []proto.ExtensionRange{
func (*ServiceOptions) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_ServiceOptions
}
func (m *ServiceOptions) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
const Default_ServiceOptions_Deprecated bool = false
@ -1459,9 +1493,9 @@ type MethodOptions struct {
// this is a formalization for deprecating methods.
Deprecated *bool `protobuf:"varint,33,opt,name=deprecated,def=0" json:"deprecated,omitempty"`
// The parser stores options it doesn't recognize here. See above.
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
proto.XXX_InternalExtensions `json:"-"`
XXX_unrecognized []byte `json:"-"`
UninterpretedOption []*UninterpretedOption `protobuf:"bytes,999,rep,name=uninterpreted_option,json=uninterpretedOption" json:"uninterpreted_option,omitempty"`
XXX_extensions map[int32]proto.Extension `json:"-"`
XXX_unrecognized []byte `json:"-"`
}
func (m *MethodOptions) Reset() { *m = MethodOptions{} }
@ -1476,6 +1510,12 @@ var extRange_MethodOptions = []proto.ExtensionRange{
func (*MethodOptions) ExtensionRangeArray() []proto.ExtensionRange {
return extRange_MethodOptions
}
func (m *MethodOptions) ExtensionMap() map[int32]proto.Extension {
if m.XXX_extensions == nil {
m.XXX_extensions = make(map[int32]proto.Extension)
}
return m.XXX_extensions
}
const Default_MethodOptions_Deprecated bool = false
@ -1889,8 +1929,6 @@ func init() {
proto.RegisterEnum("google.protobuf.FieldOptions_JSType", FieldOptions_JSType_name, FieldOptions_JSType_value)
}
func init() { proto.RegisterFile("google/protobuf/descriptor.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 2247 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xcc, 0x59, 0x4f, 0x8f, 0xdb, 0xc6,

View File

@ -26,9 +26,7 @@ var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
const _ = proto.ProtoPackageIsVersion1
// An encoded CodeGeneratorRequest is written to the plugin's stdin.
type CodeGeneratorRequest struct {
@ -202,8 +200,6 @@ func init() {
proto.RegisterType((*CodeGeneratorResponse_File)(nil), "google.protobuf.compiler.CodeGeneratorResponse.File")
}
func init() { proto.RegisterFile("google/protobuf/compiler/plugin.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 311 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x74, 0x91, 0xd1, 0x4a, 0xfb, 0x30,

View File

@ -81,9 +81,20 @@ FOO
* Boolean values: `true`, `false`
* Arrays can be made by wrapping it in `[]`. Example:
`["foo", "bar", 42]`. Arrays can contain primitives
and other arrays, but cannot contain objects. Objects must
use the block syntax shown below.
`["foo", "bar", 42]`. Arrays can contain primitives,
other arrays, and objects. As an alternative, lists
of objects can be created with repeated blocks, using
this structure:
```hcl
service {
key = "value"
}
service {
key = "value"
}
```
Objects and nested objects are created using the structure shown below:

View File

@ -517,6 +517,12 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
structType := structVal.Type()
for i := 0; i < structType.NumField(); i++ {
fieldType := structType.Field(i)
tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")
// Ignore fields with tag name "-"
if tagParts[0] == "-" {
continue
}
if fieldType.Anonymous {
fieldKind := fieldType.Type.Kind()
@ -531,7 +537,6 @@ func (d *decoder) decodeStruct(name string, node ast.Node, result reflect.Value)
// We have an embedded field. We "squash" the fields down
// if specified in the tag.
squash := false
tagParts := strings.Split(fieldType.Tag.Get(tagName), ",")
for _, tag := range tagParts[1:] {
if tag == "squash" {
squash = true

View File

@ -194,6 +194,27 @@ func TestDecode_interface(t *testing.T) {
},
},
},
{
"list_of_maps.hcl",
false,
map[string]interface{}{
"foo": []interface{}{
map[string]interface{}{"somekey1": "someval1"},
map[string]interface{}{"somekey2": "someval2", "someextrakey": "someextraval"},
},
},
},
{
"assign_deep.hcl",
false,
map[string]interface{}{
"resource": []interface{}{
map[string]interface{}{
"foo": []interface{}{
map[string]interface{}{
"bar": []map[string]interface{}{
map[string]interface{}{}}}}}}},
},
{
"structure_list.hcl",
false,
@ -269,9 +290,7 @@ func TestDecode_interface(t *testing.T) {
{
"nested_provider_bad.hcl",
true,
// This is not ideal but without significant rework of the decoder
// we get a partial result back as well as an error.
map[string]interface{}{},
nil,
},
{
@ -334,6 +353,42 @@ func TestDecode_interface(t *testing.T) {
}
}
func TestDecode_interfaceInline(t *testing.T) {
cases := []struct {
Value string
Err bool
Out interface{}
}{
{"t t e{{}}", true, nil},
{"t=0t d {}", true, map[string]interface{}{"t": 0}},
{"v=0E0v d{}", true, map[string]interface{}{"v": float64(0)}},
}
for _, tc := range cases {
t.Logf("Testing: %q", tc.Value)
var out interface{}
err := Decode(&out, tc.Value)
if (err != nil) != tc.Err {
t.Fatalf("Input: %q\n\nError: %s", tc.Value, err)
}
if !reflect.DeepEqual(out, tc.Out) {
t.Fatalf("Input: %q. Actual, Expected.\n\n%#v\n\n%#v", tc.Value, out, tc.Out)
}
var v interface{}
err = Unmarshal([]byte(tc.Value), &v)
if (err != nil) != tc.Err {
t.Fatalf("Input: %q\n\nError: %s", tc.Value, err)
}
if !reflect.DeepEqual(v, tc.Out) {
t.Fatalf("Input: %q. Actual, Expected.\n\n%#v\n\n%#v", tc.Value, out, tc.Out)
}
}
}
func TestDecode_equal(t *testing.T) {
cases := []struct {
One, Two string
@ -417,9 +472,12 @@ func TestDecode_flatMap(t *testing.T) {
}
func TestDecode_structure(t *testing.T) {
type Embedded interface{}
type V struct {
Key int
Foo string
Embedded `hcl:"-"`
Key int
Foo string
}
var actual V

View File

@ -133,6 +133,12 @@ type ObjectItem struct {
}
func (o *ObjectItem) Pos() token.Pos {
// I'm not entirely sure what causes this, but removing this causes
// a test failure. We should investigate at some point.
if len(o.Keys) == 0 {
return token.Pos{}
}
return o.Keys[0].Pos()
}

View File

@ -25,7 +25,7 @@ var (
type Options struct {
List bool // list files whose formatting differs
Write bool // write result to (source) file instead of stdout
Diff bool // display diffs instead of rewriting files
Diff bool // display diffs of formatting changes
}
func isValidFile(f os.FileInfo, extensions []string) bool {

View File

@ -79,6 +79,13 @@ func (p *Parser) objectList() (*ast.ObjectList, error) {
}
node.Add(n)
// object lists can be optionally comma-delimited e.g. when a list of maps
// is being expressed, so a comma is allowed here - it's simply consumed
tok := p.scan()
if tok.Type != token.COMMA {
p.unscan()
}
}
return node, nil
}
@ -220,8 +227,19 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
return keys, nil
case token.LBRACE:
var err error
// If we have no keys, then it is a syntax error. i.e. {{}} is not
// allowed.
if len(keys) == 0 {
err = &PosError{
Pos: p.tok.Pos,
Err: fmt.Errorf("expected: IDENT | STRING got: %s", p.tok.Type),
}
}
// object
return keys, nil
return keys, err
case token.IDENT, token.STRING:
keyCount++
keys = append(keys, &ast.ObjectKey{Token: p.tok})
@ -300,15 +318,20 @@ func (p *Parser) listType() (*ast.ListType, error) {
needComma := false
for {
tok := p.scan()
switch tok.Type {
case token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC:
if needComma {
if needComma {
switch tok.Type {
case token.COMMA, token.RBRACK:
default:
return nil, &PosError{
Pos: tok.Pos,
Err: fmt.Errorf("unexpected token: %s. Expecting %s", tok.Type, token.COMMA),
Err: fmt.Errorf(
"error parsing list, expected comma or list end, got: %s",
tok.Type),
}
}
}
switch tok.Type {
case token.NUMBER, token.FLOAT, token.STRING, token.HEREDOC:
node, err := p.literalType()
if err != nil {
return nil, err
@ -320,7 +343,7 @@ func (p *Parser) listType() (*ast.ListType, error) {
// get next list item or we are at the end
// do a look-ahead for line comment
p.scan()
if p.lineComment != nil {
if p.lineComment != nil && len(l.List) > 0 {
lit, ok := l.List[len(l.List)-1].(*ast.LiteralType)
if ok {
lit.LineComment = p.lineComment
@ -332,6 +355,18 @@ func (p *Parser) listType() (*ast.ListType, error) {
needComma = false
continue
case token.LBRACE:
// Looks like a nested object, so parse it out
node, err := p.objectType()
if err != nil {
return nil, &PosError{
Pos: tok.Pos,
Err: fmt.Errorf(
"error while trying to parse object within list: %s", err),
}
}
l.Add(node)
needComma = true
case token.BOOL:
// TODO(arslan) should we support? not supported by HCL yet
case token.LBRACK:

View File

@ -6,6 +6,7 @@ import (
"path/filepath"
"reflect"
"runtime"
"strings"
"testing"
"github.com/hashicorp/hcl/hcl/ast"
@ -99,6 +100,58 @@ EOF
}
}
func TestListOfMaps(t *testing.T) {
src := `foo = [
{key = "bar"},
{key = "baz", key2 = "qux"},
]`
p := newParser([]byte(src))
file, err := p.Parse()
if err != nil {
t.Fatalf("err: %s", err)
}
// Here we make all sorts of assumptions about the input structure w/ type
// assertions. The intent is only for this to be a "smoke test" ensuring
// parsing actually performed its duty - giving this test something a bit
// more robust than _just_ "no error occurred".
expected := []string{`"bar"`, `"baz"`, `"qux"`}
actual := make([]string, 0, 3)
ol := file.Node.(*ast.ObjectList)
objItem := ol.Items[0]
list := objItem.Val.(*ast.ListType)
for _, node := range list.List {
obj := node.(*ast.ObjectType)
for _, item := range obj.List.Items {
val := item.Val.(*ast.LiteralType)
actual = append(actual, val.Token.Text)
}
}
if !reflect.DeepEqual(expected, actual) {
t.Fatalf("Expected: %#v, got %#v", expected, actual)
}
}
func TestListOfMaps_requiresComma(t *testing.T) {
src := `foo = [
{key = "bar"}
{key = "baz"}
]`
p := newParser([]byte(src))
_, err := p.Parse()
if err == nil {
t.Fatalf("Expected error, got none!")
}
expected := "error parsing list, expected comma or list end"
if !strings.Contains(err.Error(), expected) {
t.Fatalf("Expected err:\n %s\nTo contain:\n %s\n", err, expected)
}
}
func TestObjectType(t *testing.T) {
var literals = []struct {
src string
@ -263,6 +316,10 @@ func TestParse(t *testing.T) {
"multiple.hcl",
false,
},
{
"object_list_comma.hcl",
false,
},
{
"structure.hcl",
false,
@ -279,10 +336,6 @@ func TestParse(t *testing.T) {
"complex.hcl",
false,
},
{
"assign_deep.hcl",
true,
},
{
"types.hcl",
false,
@ -332,6 +385,29 @@ func TestParse(t *testing.T) {
}
}
func TestParse_inline(t *testing.T) {
cases := []struct {
Value string
Err bool
}{
{"t t e{{}}", true},
{"o{{}}", true},
{"t t e d N{{}}", true},
{"t t e d{{}}", true},
{"N{}N{{}}", true},
{"v\nN{{}}", true},
{"v=/\n[,", true},
}
for _, tc := range cases {
t.Logf("Testing: %q", tc.Value)
_, err := Parse([]byte(tc.Value))
if (err != nil) != tc.Err {
t.Fatalf("Input: %q\n\nError: %s\n\nAST: %s", tc.Value, err)
}
}
}
// equals fails the test if exp is not equal to act.
func equals(tb testing.TB, exp, act interface{}) {
if !reflect.DeepEqual(exp, act) {

View File

@ -0,0 +1 @@
foo = {one = 1, two = 2}

View File

@ -35,6 +35,7 @@ var data = []entry{
{"comment_aligned.input", "comment_aligned.golden"},
{"comment_standalone.input", "comment_standalone.golden"},
{"empty_block.input", "empty_block.golden"},
{"list_of_objects.input", "list_of_objects.golden"},
}
func TestFiles(t *testing.T) {

View File

@ -0,0 +1,10 @@
list_of_objects = [
{
key1 = "value1"
key2 = "value2"
},
{
key3 = "value3"
key4 = "value4"
},
]

View File

@ -0,0 +1,10 @@
list_of_objects = [
{
key1 = "value1"
key2 = "value2"
},
{
key3 = "value3"
key4 = "value4"
}
]

View File

@ -525,16 +525,27 @@ func (s *Scanner) scanEscape() rune {
// scanDigits scans a rune with the given base for n times. For example an
// octal notation \184 would yield in scanDigits(ch, 8, 3)
func (s *Scanner) scanDigits(ch rune, base, n int) rune {
start := n
for n > 0 && digitVal(ch) < base {
ch = s.next()
if ch == eof {
// If we see an EOF, we halt any more scanning of digits
// immediately.
break
}
n--
}
if n > 0 {
s.err("illegal char escape")
}
// we scanned all digits, put the last non digit char back
s.unread()
if n != start {
// we scanned all digits, put the last non digit char back,
// only if we read anything at all
s.unread()
}
return ch
}

View File

@ -283,6 +283,11 @@ func TestPosition(t *testing.T) {
}
}
func TestNullChar(t *testing.T) {
s := New([]byte("\"\\0"))
s.Scan() // Used to panic
}
func TestComment(t *testing.T) {
testTokenList(t, tokenLists["comment"])
}
@ -378,7 +383,7 @@ func TestRealExample(t *testing.T) {
Main interface
EOF
}
network_interface {
device_index = 1
description = <<-EOF

View File

@ -128,6 +128,12 @@ func (p *Parser) objectKey() ([]*ast.ObjectKey, error) {
Token: p.tok.HCLToken(),
})
case token.COLON:
// If we have a zero keycount it means that we never got
// an object key, i.e. `{ :`. This is a syntax error.
if keyCount == 0 {
return nil, fmt.Errorf("expected: STRING got: %s", p.tok.Type)
}
// Done
return keys, nil
case token.ILLEGAL:

View File

@ -311,6 +311,10 @@ func TestParse(t *testing.T) {
"types.json",
false,
},
{
"bad_input_128.json",
true,
},
}
const fixtureDir = "./test-fixtures"
@ -328,6 +332,22 @@ func TestParse(t *testing.T) {
}
}
func TestParse_inline(t *testing.T) {
cases := []struct {
Value string
Err bool
}{
{"{:{", true},
}
for _, tc := range cases {
_, err := Parse([]byte(tc.Value))
if (err != nil) != tc.Err {
t.Fatalf("Input: %q\n\nError: %s", tc.Value, err)
}
}
}
// equals fails the test if exp is not equal to act.
func equals(tb testing.TB, exp, act interface{}) {
if !reflect.DeepEqual(exp, act) {

View File

@ -0,0 +1 @@
{:{

View File

@ -0,0 +1,4 @@
foo = [
{somekey1 = "someval1"},
{somekey2 = "someval2", someextrakey = "someextraval"},
]

View File

@ -47,10 +47,17 @@ var _ = proto.Marshal
var _ = fmt.Errorf
var _ = math.Inf
// This is a compile-time assertion to ensure that this generated file
// is compatible with the proto package it is being compiled against.
// A compilation error at this line likely means your copy of the
// proto package needs to be updated.
const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package
type Reject_RejectType int32
const (
// TODO ??
// The rejection reason is unknown (details should be available
// in Reject.reason).
Reject_None Reject_RejectType = 0
// The client attempted to connect with an incompatible version.
Reject_WrongVersion Reject_RejectType = 1
@ -110,6 +117,7 @@ func (x *Reject_RejectType) UnmarshalJSON(data []byte) error {
*x = Reject_RejectType(value)
return nil
}
func (Reject_RejectType) EnumDescriptor() ([]byte, []int) { return fileDescriptor0, []int{4, 0} }
type PermissionDenied_DenyType int32
@ -180,6 +188,9 @@ func (x *PermissionDenied_DenyType) UnmarshalJSON(data []byte) error {
*x = PermissionDenied_DenyType(value)
return nil
}
func (PermissionDenied_DenyType) EnumDescriptor() ([]byte, []int) {
return fileDescriptor0, []int{12, 0}
}
type ContextActionModify_Context int32
@ -219,6 +230,9 @@ func (x *ContextActionModify_Context) UnmarshalJSON(data []byte) error {
*x = ContextActionModify_Context(value)
return nil
}
func (ContextActionModify_Context) EnumDescriptor() ([]byte, []int) {
return fileDescriptor0, []int{16, 0}
}
type ContextActionModify_Operation int32
@ -252,6 +266,9 @@ func (x *ContextActionModify_Operation) UnmarshalJSON(data []byte) error {
*x = ContextActionModify_Operation(value)
return nil
}
func (ContextActionModify_Operation) EnumDescriptor() ([]byte, []int) {
return fileDescriptor0, []int{16, 1}
}
type Version struct {
// 2-byte Major, 1-byte Minor and 1-byte Patch version number.
@ -261,13 +278,14 @@ type Version struct {
// Client OS name.
Os *string `protobuf:"bytes,3,opt,name=os" json:"os,omitempty"`
// Client OS version.
OsVersion *string `protobuf:"bytes,4,opt,name=os_version" json:"os_version,omitempty"`
OsVersion *string `protobuf:"bytes,4,opt,name=os_version,json=osVersion" json:"os_version,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *Version) Reset() { *m = Version{} }
func (m *Version) String() string { return proto.CompactTextString(m) }
func (*Version) ProtoMessage() {}
func (m *Version) Reset() { *m = Version{} }
func (m *Version) String() string { return proto.CompactTextString(m) }
func (*Version) ProtoMessage() {}
func (*Version) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} }
func (m *Version) GetVersion() uint32 {
if m != nil && m.Version != nil {
@ -304,9 +322,10 @@ type UDPTunnel struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *UDPTunnel) Reset() { *m = UDPTunnel{} }
func (m *UDPTunnel) String() string { return proto.CompactTextString(m) }
func (*UDPTunnel) ProtoMessage() {}
func (m *UDPTunnel) Reset() { *m = UDPTunnel{} }
func (m *UDPTunnel) String() string { return proto.CompactTextString(m) }
func (*UDPTunnel) ProtoMessage() {}
func (*UDPTunnel) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} }
func (m *UDPTunnel) GetPacket() []byte {
if m != nil {
@ -324,14 +343,15 @@ type Authenticate struct {
// Additional access tokens for server ACL groups.
Tokens []string `protobuf:"bytes,3,rep,name=tokens" json:"tokens,omitempty"`
// A list of CELT bitstream version constants supported by the client.
CeltVersions []int32 `protobuf:"varint,4,rep,name=celt_versions" json:"celt_versions,omitempty"`
CeltVersions []int32 `protobuf:"varint,4,rep,name=celt_versions,json=celtVersions" json:"celt_versions,omitempty"`
Opus *bool `protobuf:"varint,5,opt,name=opus,def=0" json:"opus,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *Authenticate) Reset() { *m = Authenticate{} }
func (m *Authenticate) String() string { return proto.CompactTextString(m) }
func (*Authenticate) ProtoMessage() {}
func (m *Authenticate) Reset() { *m = Authenticate{} }
func (m *Authenticate) String() string { return proto.CompactTextString(m) }
func (*Authenticate) ProtoMessage() {}
func (*Authenticate) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} }
const Default_Authenticate_Opus bool = false
@ -385,23 +405,24 @@ type Ping struct {
// The amount of nonce resyncs.
Resync *uint32 `protobuf:"varint,5,opt,name=resync" json:"resync,omitempty"`
// The total amount of UDP packets received.
UdpPackets *uint32 `protobuf:"varint,6,opt,name=udp_packets" json:"udp_packets,omitempty"`
UdpPackets *uint32 `protobuf:"varint,6,opt,name=udp_packets,json=udpPackets" json:"udp_packets,omitempty"`
// The total amount of TCP packets received.
TcpPackets *uint32 `protobuf:"varint,7,opt,name=tcp_packets" json:"tcp_packets,omitempty"`
TcpPackets *uint32 `protobuf:"varint,7,opt,name=tcp_packets,json=tcpPackets" json:"tcp_packets,omitempty"`
// UDP ping average.
UdpPingAvg *float32 `protobuf:"fixed32,8,opt,name=udp_ping_avg" json:"udp_ping_avg,omitempty"`
UdpPingAvg *float32 `protobuf:"fixed32,8,opt,name=udp_ping_avg,json=udpPingAvg" json:"udp_ping_avg,omitempty"`
// UDP ping variance.
UdpPingVar *float32 `protobuf:"fixed32,9,opt,name=udp_ping_var" json:"udp_ping_var,omitempty"`
UdpPingVar *float32 `protobuf:"fixed32,9,opt,name=udp_ping_var,json=udpPingVar" json:"udp_ping_var,omitempty"`
// TCP ping average.
TcpPingAvg *float32 `protobuf:"fixed32,10,opt,name=tcp_ping_avg" json:"tcp_ping_avg,omitempty"`
TcpPingAvg *float32 `protobuf:"fixed32,10,opt,name=tcp_ping_avg,json=tcpPingAvg" json:"tcp_ping_avg,omitempty"`
// TCP ping variance.
TcpPingVar *float32 `protobuf:"fixed32,11,opt,name=tcp_ping_var" json:"tcp_ping_var,omitempty"`
TcpPingVar *float32 `protobuf:"fixed32,11,opt,name=tcp_ping_var,json=tcpPingVar" json:"tcp_ping_var,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *Ping) Reset() { *m = Ping{} }
func (m *Ping) String() string { return proto.CompactTextString(m) }
func (*Ping) ProtoMessage() {}
func (m *Ping) Reset() { *m = Ping{} }
func (m *Ping) String() string { return proto.CompactTextString(m) }
func (*Ping) ProtoMessage() {}
func (*Ping) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} }
func (m *Ping) GetTimestamp() uint64 {
if m != nil && m.Timestamp != nil {
@ -489,9 +510,10 @@ type Reject struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *Reject) Reset() { *m = Reject{} }
func (m *Reject) String() string { return proto.CompactTextString(m) }
func (*Reject) ProtoMessage() {}
func (m *Reject) Reset() { *m = Reject{} }
func (m *Reject) String() string { return proto.CompactTextString(m) }
func (*Reject) ProtoMessage() {}
func (*Reject) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} }
func (m *Reject) GetType() Reject_RejectType {
if m != nil && m.Type != nil {
@ -513,17 +535,18 @@ type ServerSync struct {
// The session of the current user.
Session *uint32 `protobuf:"varint,1,opt,name=session" json:"session,omitempty"`
// Maximum bandwidth that the user should use.
MaxBandwidth *uint32 `protobuf:"varint,2,opt,name=max_bandwidth" json:"max_bandwidth,omitempty"`
MaxBandwidth *uint32 `protobuf:"varint,2,opt,name=max_bandwidth,json=maxBandwidth" json:"max_bandwidth,omitempty"`
// Server welcome text.
WelcomeText *string `protobuf:"bytes,3,opt,name=welcome_text" json:"welcome_text,omitempty"`
// Current user permissions TODO: Confirm??
WelcomeText *string `protobuf:"bytes,3,opt,name=welcome_text,json=welcomeText" json:"welcome_text,omitempty"`
// Current user permissions in the root channel.
Permissions *uint64 `protobuf:"varint,4,opt,name=permissions" json:"permissions,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *ServerSync) Reset() { *m = ServerSync{} }
func (m *ServerSync) String() string { return proto.CompactTextString(m) }
func (*ServerSync) ProtoMessage() {}
func (m *ServerSync) Reset() { *m = ServerSync{} }
func (m *ServerSync) String() string { return proto.CompactTextString(m) }
func (*ServerSync) ProtoMessage() {}
func (*ServerSync) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{5} }
func (m *ServerSync) GetSession() uint32 {
if m != nil && m.Session != nil {
@ -556,13 +579,14 @@ func (m *ServerSync) GetPermissions() uint64 {
// Sent by the client when it wants a channel removed. Sent by the server when
// a channel has been removed and clients should be notified.
type ChannelRemove struct {
ChannelId *uint32 `protobuf:"varint,1,req,name=channel_id" json:"channel_id,omitempty"`
ChannelId *uint32 `protobuf:"varint,1,req,name=channel_id,json=channelId" json:"channel_id,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *ChannelRemove) Reset() { *m = ChannelRemove{} }
func (m *ChannelRemove) String() string { return proto.CompactTextString(m) }
func (*ChannelRemove) ProtoMessage() {}
func (m *ChannelRemove) Reset() { *m = ChannelRemove{} }
func (m *ChannelRemove) String() string { return proto.CompactTextString(m) }
func (*ChannelRemove) ProtoMessage() {}
func (*ChannelRemove) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{6} }
func (m *ChannelRemove) GetChannelId() uint32 {
if m != nil && m.ChannelId != nil {
@ -576,7 +600,7 @@ func (m *ChannelRemove) GetChannelId() uint32 {
// updated. Client may use this message to update said channel properties.
type ChannelState struct {
// Unique ID for the channel within the server.
ChannelId *uint32 `protobuf:"varint,1,opt,name=channel_id" json:"channel_id,omitempty"`
ChannelId *uint32 `protobuf:"varint,1,opt,name=channel_id,json=channelId" json:"channel_id,omitempty"`
// channel_id of the parent channel.
Parent *uint32 `protobuf:"varint,2,opt,name=parent" json:"parent,omitempty"`
// UTF-8 encoded channel name.
@ -588,25 +612,26 @@ type ChannelState struct {
// 128 bytes
Description *string `protobuf:"bytes,5,opt,name=description" json:"description,omitempty"`
// A collection of channel_id values that should be added to links.
LinksAdd []uint32 `protobuf:"varint,6,rep,name=links_add" json:"links_add,omitempty"`
LinksAdd []uint32 `protobuf:"varint,6,rep,name=links_add,json=linksAdd" json:"links_add,omitempty"`
// A collection of channel_id values that should be removed from links.
LinksRemove []uint32 `protobuf:"varint,7,rep,name=links_remove" json:"links_remove,omitempty"`
LinksRemove []uint32 `protobuf:"varint,7,rep,name=links_remove,json=linksRemove" json:"links_remove,omitempty"`
// True if the channel is temporary.
Temporary *bool `protobuf:"varint,8,opt,name=temporary,def=0" json:"temporary,omitempty"`
// Position weight to tweak the channel position in the channel list.
Position *int32 `protobuf:"varint,9,opt,name=position,def=0" json:"position,omitempty"`
// SHA1 hash of the description if the description is 128 bytes or more.
DescriptionHash []byte `protobuf:"bytes,10,opt,name=description_hash" json:"description_hash,omitempty"`
DescriptionHash []byte `protobuf:"bytes,10,opt,name=description_hash,json=descriptionHash" json:"description_hash,omitempty"`
// Maximum number of users allowed in the channel. If this value is zero,
// the maximum number of users allowed in the channel is given by the
// server's "usersperchannel" setting.
MaxUsers *uint32 `protobuf:"varint,11,opt,name=max_users" json:"max_users,omitempty"`
MaxUsers *uint32 `protobuf:"varint,11,opt,name=max_users,json=maxUsers" json:"max_users,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *ChannelState) Reset() { *m = ChannelState{} }
func (m *ChannelState) String() string { return proto.CompactTextString(m) }
func (*ChannelState) ProtoMessage() {}
func (m *ChannelState) Reset() { *m = ChannelState{} }
func (m *ChannelState) String() string { return proto.CompactTextString(m) }
func (*ChannelState) ProtoMessage() {}
func (*ChannelState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{7} }
const Default_ChannelState_Temporary bool = false
const Default_ChannelState_Position int32 = 0
@ -705,9 +730,10 @@ type UserRemove struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *UserRemove) Reset() { *m = UserRemove{} }
func (m *UserRemove) String() string { return proto.CompactTextString(m) }
func (*UserRemove) ProtoMessage() {}
func (m *UserRemove) Reset() { *m = UserRemove{} }
func (m *UserRemove) String() string { return proto.CompactTextString(m) }
func (*UserRemove) ProtoMessage() {}
func (*UserRemove) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{8} }
func (m *UserRemove) GetSession() uint32 {
if m != nil && m.Session != nil {
@ -749,9 +775,9 @@ type UserState struct {
// User name, UTF-8 encoded.
Name *string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"`
// Registered user ID if the user is registered.
UserId *uint32 `protobuf:"varint,4,opt,name=user_id" json:"user_id,omitempty"`
UserId *uint32 `protobuf:"varint,4,opt,name=user_id,json=userId" json:"user_id,omitempty"`
// Channel on which the user is.
ChannelId *uint32 `protobuf:"varint,5,opt,name=channel_id" json:"channel_id,omitempty"`
ChannelId *uint32 `protobuf:"varint,5,opt,name=channel_id,json=channelId" json:"channel_id,omitempty"`
// True if the user is muted by admin.
Mute *bool `protobuf:"varint,6,opt,name=mute" json:"mute,omitempty"`
// True if the user is deafened by admin.
@ -760,33 +786,39 @@ type UserState struct {
// being muted.
Suppress *bool `protobuf:"varint,8,opt,name=suppress" json:"suppress,omitempty"`
// True if the user has muted self.
SelfMute *bool `protobuf:"varint,9,opt,name=self_mute" json:"self_mute,omitempty"`
SelfMute *bool `protobuf:"varint,9,opt,name=self_mute,json=selfMute" json:"self_mute,omitempty"`
// True if the user has deafened self.
SelfDeaf *bool `protobuf:"varint,10,opt,name=self_deaf" json:"self_deaf,omitempty"`
SelfDeaf *bool `protobuf:"varint,10,opt,name=self_deaf,json=selfDeaf" json:"self_deaf,omitempty"`
// User image if it is less than 128 bytes.
Texture []byte `protobuf:"bytes,11,opt,name=texture" json:"texture,omitempty"`
// TODO ??
PluginContext []byte `protobuf:"bytes,12,opt,name=plugin_context" json:"plugin_context,omitempty"`
// TODO ??
PluginIdentity *string `protobuf:"bytes,13,opt,name=plugin_identity" json:"plugin_identity,omitempty"`
// The positional audio plugin identifier.
// Positional audio information is only sent to users who share
// identical plugin contexts.
//
// This value is not trasmitted to clients.
PluginContext []byte `protobuf:"bytes,12,opt,name=plugin_context,json=pluginContext" json:"plugin_context,omitempty"`
// The user's plugin-specific identity.
// This value is not transmitted to clients.
PluginIdentity *string `protobuf:"bytes,13,opt,name=plugin_identity,json=pluginIdentity" json:"plugin_identity,omitempty"`
// User comment if it is less than 128 bytes.
Comment *string `protobuf:"bytes,14,opt,name=comment" json:"comment,omitempty"`
// The hash of the user certificate.
Hash *string `protobuf:"bytes,15,opt,name=hash" json:"hash,omitempty"`
// SHA1 hash of the user comment if it 128 bytes or more.
CommentHash []byte `protobuf:"bytes,16,opt,name=comment_hash" json:"comment_hash,omitempty"`
CommentHash []byte `protobuf:"bytes,16,opt,name=comment_hash,json=commentHash" json:"comment_hash,omitempty"`
// SHA1 hash of the user picture if it 128 bytes or more.
TextureHash []byte `protobuf:"bytes,17,opt,name=texture_hash" json:"texture_hash,omitempty"`
TextureHash []byte `protobuf:"bytes,17,opt,name=texture_hash,json=textureHash" json:"texture_hash,omitempty"`
// True if the user is a priority speaker.
PrioritySpeaker *bool `protobuf:"varint,18,opt,name=priority_speaker" json:"priority_speaker,omitempty"`
PrioritySpeaker *bool `protobuf:"varint,18,opt,name=priority_speaker,json=prioritySpeaker" json:"priority_speaker,omitempty"`
// True if the user is currently recording.
Recording *bool `protobuf:"varint,19,opt,name=recording" json:"recording,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *UserState) Reset() { *m = UserState{} }
func (m *UserState) String() string { return proto.CompactTextString(m) }
func (*UserState) ProtoMessage() {}
func (m *UserState) Reset() { *m = UserState{} }
func (m *UserState) String() string { return proto.CompactTextString(m) }
func (*UserState) ProtoMessage() {}
func (*UserState) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} }
func (m *UserState) GetSession() uint32 {
if m != nil && m.Session != nil {
@ -933,9 +965,10 @@ type BanList struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *BanList) Reset() { *m = BanList{} }
func (m *BanList) String() string { return proto.CompactTextString(m) }
func (*BanList) ProtoMessage() {}
func (m *BanList) Reset() { *m = BanList{} }
func (m *BanList) String() string { return proto.CompactTextString(m) }
func (*BanList) ProtoMessage() {}
func (*BanList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10} }
const Default_BanList_Query bool = false
@ -960,7 +993,7 @@ type BanList_BanEntry struct {
Mask *uint32 `protobuf:"varint,2,req,name=mask" json:"mask,omitempty"`
// User name for identification purposes (does not affect the ban).
Name *string `protobuf:"bytes,3,opt,name=name" json:"name,omitempty"`
// TODO ??
// The certificate hash of the banned user.
Hash *string `protobuf:"bytes,4,opt,name=hash" json:"hash,omitempty"`
// Reason for the ban (does not affect the ban).
Reason *string `protobuf:"bytes,5,opt,name=reason" json:"reason,omitempty"`
@ -971,9 +1004,10 @@ type BanList_BanEntry struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *BanList_BanEntry) Reset() { *m = BanList_BanEntry{} }
func (m *BanList_BanEntry) String() string { return proto.CompactTextString(m) }
func (*BanList_BanEntry) ProtoMessage() {}
func (m *BanList_BanEntry) Reset() { *m = BanList_BanEntry{} }
func (m *BanList_BanEntry) String() string { return proto.CompactTextString(m) }
func (*BanList_BanEntry) ProtoMessage() {}
func (*BanList_BanEntry) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{10, 0} }
func (m *BanList_BanEntry) GetAddress() []byte {
if m != nil {
@ -1032,18 +1066,19 @@ type TextMessage struct {
Session []uint32 `protobuf:"varint,2,rep,name=session" json:"session,omitempty"`
// The channels to which the message is sent, identified by their
// channel_ids.
ChannelId []uint32 `protobuf:"varint,3,rep,name=channel_id" json:"channel_id,omitempty"`
ChannelId []uint32 `protobuf:"varint,3,rep,name=channel_id,json=channelId" json:"channel_id,omitempty"`
// The root channels when sending message recursively to several channels,
// identified by their channel_ids.
TreeId []uint32 `protobuf:"varint,4,rep,name=tree_id" json:"tree_id,omitempty"`
TreeId []uint32 `protobuf:"varint,4,rep,name=tree_id,json=treeId" json:"tree_id,omitempty"`
// The UTF-8 encoded message. May be HTML if the server allows.
Message *string `protobuf:"bytes,5,req,name=message" json:"message,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *TextMessage) Reset() { *m = TextMessage{} }
func (m *TextMessage) String() string { return proto.CompactTextString(m) }
func (*TextMessage) ProtoMessage() {}
func (m *TextMessage) Reset() { *m = TextMessage{} }
func (m *TextMessage) String() string { return proto.CompactTextString(m) }
func (*TextMessage) ProtoMessage() {}
func (*TextMessage) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{11} }
func (m *TextMessage) GetActor() uint32 {
if m != nil && m.Actor != nil {
@ -1085,7 +1120,7 @@ type PermissionDenied struct {
Permission *uint32 `protobuf:"varint,1,opt,name=permission" json:"permission,omitempty"`
// channel_id for the channel where the permission was denied when type is
// Permission.
ChannelId *uint32 `protobuf:"varint,2,opt,name=channel_id" json:"channel_id,omitempty"`
ChannelId *uint32 `protobuf:"varint,2,opt,name=channel_id,json=channelId" json:"channel_id,omitempty"`
// The user who was denied permissions, identified by session.
Session *uint32 `protobuf:"varint,3,opt,name=session" json:"session,omitempty"`
// Textual reason for the denial.
@ -1097,9 +1132,10 @@ type PermissionDenied struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *PermissionDenied) Reset() { *m = PermissionDenied{} }
func (m *PermissionDenied) String() string { return proto.CompactTextString(m) }
func (*PermissionDenied) ProtoMessage() {}
func (m *PermissionDenied) Reset() { *m = PermissionDenied{} }
func (m *PermissionDenied) String() string { return proto.CompactTextString(m) }
func (*PermissionDenied) ProtoMessage() {}
func (*PermissionDenied) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{12} }
func (m *PermissionDenied) GetPermission() uint32 {
if m != nil && m.Permission != nil {
@ -1145,9 +1181,9 @@ func (m *PermissionDenied) GetName() string {
type ACL struct {
// Channel ID of the channel this message affects.
ChannelId *uint32 `protobuf:"varint,1,req,name=channel_id" json:"channel_id,omitempty"`
ChannelId *uint32 `protobuf:"varint,1,req,name=channel_id,json=channelId" json:"channel_id,omitempty"`
// True if the channel inherits its parent's ACLs.
InheritAcls *bool `protobuf:"varint,2,opt,name=inherit_acls,def=1" json:"inherit_acls,omitempty"`
InheritAcls *bool `protobuf:"varint,2,opt,name=inherit_acls,json=inheritAcls,def=1" json:"inherit_acls,omitempty"`
// User group specifications.
Groups []*ACL_ChanGroup `protobuf:"bytes,3,rep,name=groups" json:"groups,omitempty"`
// ACL specifications.
@ -1157,9 +1193,10 @@ type ACL struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *ACL) Reset() { *m = ACL{} }
func (m *ACL) String() string { return proto.CompactTextString(m) }
func (*ACL) ProtoMessage() {}
func (m *ACL) Reset() { *m = ACL{} }
func (m *ACL) String() string { return proto.CompactTextString(m) }
func (*ACL) ProtoMessage() {}
func (*ACL) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13} }
const Default_ACL_InheritAcls bool = true
const Default_ACL_Query bool = false
@ -1214,13 +1251,14 @@ type ACL_ChanGroup struct {
// has been inherited, identified by user_id.
Remove []uint32 `protobuf:"varint,6,rep,name=remove" json:"remove,omitempty"`
// Users inherited, identified by user_id.
InheritedMembers []uint32 `protobuf:"varint,7,rep,name=inherited_members" json:"inherited_members,omitempty"`
InheritedMembers []uint32 `protobuf:"varint,7,rep,name=inherited_members,json=inheritedMembers" json:"inherited_members,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *ACL_ChanGroup) Reset() { *m = ACL_ChanGroup{} }
func (m *ACL_ChanGroup) String() string { return proto.CompactTextString(m) }
func (*ACL_ChanGroup) ProtoMessage() {}
func (m *ACL_ChanGroup) Reset() { *m = ACL_ChanGroup{} }
func (m *ACL_ChanGroup) String() string { return proto.CompactTextString(m) }
func (*ACL_ChanGroup) ProtoMessage() {}
func (*ACL_ChanGroup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13, 0} }
const Default_ACL_ChanGroup_Inherited bool = true
const Default_ACL_ChanGroup_Inherit bool = true
@ -1277,13 +1315,13 @@ func (m *ACL_ChanGroup) GetInheritedMembers() []uint32 {
type ACL_ChanACL struct {
// True if this ACL applies to the current channel.
ApplyHere *bool `protobuf:"varint,1,opt,name=apply_here,def=1" json:"apply_here,omitempty"`
ApplyHere *bool `protobuf:"varint,1,opt,name=apply_here,json=applyHere,def=1" json:"apply_here,omitempty"`
// True if this ACL applies to the sub channels.
ApplySubs *bool `protobuf:"varint,2,opt,name=apply_subs,def=1" json:"apply_subs,omitempty"`
ApplySubs *bool `protobuf:"varint,2,opt,name=apply_subs,json=applySubs,def=1" json:"apply_subs,omitempty"`
// True if the ACL has been inherited from the parent.
Inherited *bool `protobuf:"varint,3,opt,name=inherited,def=1" json:"inherited,omitempty"`
// ID of the user that is affected by this ACL.
UserId *uint32 `protobuf:"varint,4,opt,name=user_id" json:"user_id,omitempty"`
UserId *uint32 `protobuf:"varint,4,opt,name=user_id,json=userId" json:"user_id,omitempty"`
// ID of the group that is affected by this ACL.
Group *string `protobuf:"bytes,5,opt,name=group" json:"group,omitempty"`
// Bit flag field of the permissions granted by this ACL.
@ -1293,9 +1331,10 @@ type ACL_ChanACL struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *ACL_ChanACL) Reset() { *m = ACL_ChanACL{} }
func (m *ACL_ChanACL) String() string { return proto.CompactTextString(m) }
func (*ACL_ChanACL) ProtoMessage() {}
func (m *ACL_ChanACL) Reset() { *m = ACL_ChanACL{} }
func (m *ACL_ChanACL) String() string { return proto.CompactTextString(m) }
func (*ACL_ChanACL) ProtoMessage() {}
func (*ACL_ChanACL) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{13, 1} }
const Default_ACL_ChanACL_ApplyHere bool = true
const Default_ACL_ChanACL_ApplySubs bool = true
@ -1361,9 +1400,10 @@ type QueryUsers struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *QueryUsers) Reset() { *m = QueryUsers{} }
func (m *QueryUsers) String() string { return proto.CompactTextString(m) }
func (*QueryUsers) ProtoMessage() {}
func (m *QueryUsers) Reset() { *m = QueryUsers{} }
func (m *QueryUsers) String() string { return proto.CompactTextString(m) }
func (*QueryUsers) ProtoMessage() {}
func (*QueryUsers) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{14} }
func (m *QueryUsers) GetIds() []uint32 {
if m != nil {
@ -1387,15 +1427,16 @@ type CryptSetup struct {
// Encryption key.
Key []byte `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"`
// Client nonce.
ClientNonce []byte `protobuf:"bytes,2,opt,name=client_nonce" json:"client_nonce,omitempty"`
ClientNonce []byte `protobuf:"bytes,2,opt,name=client_nonce,json=clientNonce" json:"client_nonce,omitempty"`
// Server nonce.
ServerNonce []byte `protobuf:"bytes,3,opt,name=server_nonce" json:"server_nonce,omitempty"`
ServerNonce []byte `protobuf:"bytes,3,opt,name=server_nonce,json=serverNonce" json:"server_nonce,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *CryptSetup) Reset() { *m = CryptSetup{} }
func (m *CryptSetup) String() string { return proto.CompactTextString(m) }
func (*CryptSetup) ProtoMessage() {}
func (m *CryptSetup) Reset() { *m = CryptSetup{} }
func (m *CryptSetup) String() string { return proto.CompactTextString(m) }
func (*CryptSetup) ProtoMessage() {}
func (*CryptSetup) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{15} }
func (m *CryptSetup) GetKey() []byte {
if m != nil {
@ -1429,9 +1470,10 @@ type ContextActionModify struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *ContextActionModify) Reset() { *m = ContextActionModify{} }
func (m *ContextActionModify) String() string { return proto.CompactTextString(m) }
func (*ContextActionModify) ProtoMessage() {}
func (m *ContextActionModify) Reset() { *m = ContextActionModify{} }
func (m *ContextActionModify) String() string { return proto.CompactTextString(m) }
func (*ContextActionModify) ProtoMessage() {}
func (*ContextActionModify) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{16} }
func (m *ContextActionModify) GetAction() string {
if m != nil && m.Action != nil {
@ -1466,15 +1508,16 @@ type ContextAction struct {
// The target User for the action, identified by session.
Session *uint32 `protobuf:"varint,1,opt,name=session" json:"session,omitempty"`
// The target Channel for the action, identified by channel_id.
ChannelId *uint32 `protobuf:"varint,2,opt,name=channel_id" json:"channel_id,omitempty"`
ChannelId *uint32 `protobuf:"varint,2,opt,name=channel_id,json=channelId" json:"channel_id,omitempty"`
// The action that should be executed.
Action *string `protobuf:"bytes,3,req,name=action" json:"action,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *ContextAction) Reset() { *m = ContextAction{} }
func (m *ContextAction) String() string { return proto.CompactTextString(m) }
func (*ContextAction) ProtoMessage() {}
func (m *ContextAction) Reset() { *m = ContextAction{} }
func (m *ContextAction) String() string { return proto.CompactTextString(m) }
func (*ContextAction) ProtoMessage() {}
func (*ContextAction) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{17} }
func (m *ContextAction) GetSession() uint32 {
if m != nil && m.Session != nil {
@ -1504,9 +1547,10 @@ type UserList struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *UserList) Reset() { *m = UserList{} }
func (m *UserList) String() string { return proto.CompactTextString(m) }
func (*UserList) ProtoMessage() {}
func (m *UserList) Reset() { *m = UserList{} }
func (m *UserList) String() string { return proto.CompactTextString(m) }
func (*UserList) ProtoMessage() {}
func (*UserList) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18} }
func (m *UserList) GetUsers() []*UserList_User {
if m != nil {
@ -1517,17 +1561,18 @@ func (m *UserList) GetUsers() []*UserList_User {
type UserList_User struct {
// Registered user ID.
UserId *uint32 `protobuf:"varint,1,req,name=user_id" json:"user_id,omitempty"`
UserId *uint32 `protobuf:"varint,1,req,name=user_id,json=userId" json:"user_id,omitempty"`
// Registered user name.
Name *string `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
LastSeen *string `protobuf:"bytes,3,opt,name=last_seen" json:"last_seen,omitempty"`
LastChannel *uint32 `protobuf:"varint,4,opt,name=last_channel" json:"last_channel,omitempty"`
LastSeen *string `protobuf:"bytes,3,opt,name=last_seen,json=lastSeen" json:"last_seen,omitempty"`
LastChannel *uint32 `protobuf:"varint,4,opt,name=last_channel,json=lastChannel" json:"last_channel,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *UserList_User) Reset() { *m = UserList_User{} }
func (m *UserList_User) String() string { return proto.CompactTextString(m) }
func (*UserList_User) ProtoMessage() {}
func (m *UserList_User) Reset() { *m = UserList_User{} }
func (m *UserList_User) String() string { return proto.CompactTextString(m) }
func (*UserList_User) ProtoMessage() {}
func (*UserList_User) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{18, 0} }
func (m *UserList_User) GetUserId() uint32 {
if m != nil && m.UserId != nil {
@ -1569,9 +1614,10 @@ type VoiceTarget struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *VoiceTarget) Reset() { *m = VoiceTarget{} }
func (m *VoiceTarget) String() string { return proto.CompactTextString(m) }
func (*VoiceTarget) ProtoMessage() {}
func (m *VoiceTarget) Reset() { *m = VoiceTarget{} }
func (m *VoiceTarget) String() string { return proto.CompactTextString(m) }
func (*VoiceTarget) ProtoMessage() {}
func (*VoiceTarget) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19} }
func (m *VoiceTarget) GetId() uint32 {
if m != nil && m.Id != nil {
@ -1590,9 +1636,9 @@ func (m *VoiceTarget) GetTargets() []*VoiceTarget_Target {
type VoiceTarget_Target struct {
// Users that are included as targets.
Session []uint32 `protobuf:"varint,1,rep,name=session" json:"session,omitempty"`
// Channels that are included as targets.
ChannelId *uint32 `protobuf:"varint,2,opt,name=channel_id" json:"channel_id,omitempty"`
// TODO ??
// Channel that is included as a target.
ChannelId *uint32 `protobuf:"varint,2,opt,name=channel_id,json=channelId" json:"channel_id,omitempty"`
// ACL group that is included as a target.
Group *string `protobuf:"bytes,3,opt,name=group" json:"group,omitempty"`
// True if the voice should follow links from the specified channel.
Links *bool `protobuf:"varint,4,opt,name=links,def=0" json:"links,omitempty"`
@ -1602,9 +1648,10 @@ type VoiceTarget_Target struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *VoiceTarget_Target) Reset() { *m = VoiceTarget_Target{} }
func (m *VoiceTarget_Target) String() string { return proto.CompactTextString(m) }
func (*VoiceTarget_Target) ProtoMessage() {}
func (m *VoiceTarget_Target) Reset() { *m = VoiceTarget_Target{} }
func (m *VoiceTarget_Target) String() string { return proto.CompactTextString(m) }
func (*VoiceTarget_Target) ProtoMessage() {}
func (*VoiceTarget_Target) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{19, 0} }
const Default_VoiceTarget_Target_Links bool = false
const Default_VoiceTarget_Target_Children bool = false
@ -1649,7 +1696,7 @@ func (m *VoiceTarget_Target) GetChildren() bool {
// channel permissions.
type PermissionQuery struct {
// channel_id of the channel for which the permissions are queried.
ChannelId *uint32 `protobuf:"varint,1,opt,name=channel_id" json:"channel_id,omitempty"`
ChannelId *uint32 `protobuf:"varint,1,opt,name=channel_id,json=channelId" json:"channel_id,omitempty"`
// Channel permissions.
Permissions *uint32 `protobuf:"varint,2,opt,name=permissions" json:"permissions,omitempty"`
// True if the client should drop its current permission information for all
@ -1658,9 +1705,10 @@ type PermissionQuery struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *PermissionQuery) Reset() { *m = PermissionQuery{} }
func (m *PermissionQuery) String() string { return proto.CompactTextString(m) }
func (*PermissionQuery) ProtoMessage() {}
func (m *PermissionQuery) Reset() { *m = PermissionQuery{} }
func (m *PermissionQuery) String() string { return proto.CompactTextString(m) }
func (*PermissionQuery) ProtoMessage() {}
func (*PermissionQuery) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{20} }
const Default_PermissionQuery_Flush bool = false
@ -1693,14 +1741,15 @@ type CodecVersion struct {
// The version of the CELT Beta codec.
Beta *int32 `protobuf:"varint,2,req,name=beta" json:"beta,omitempty"`
// True if the user should prefer Alpha over Beta.
PreferAlpha *bool `protobuf:"varint,3,req,name=prefer_alpha,def=1" json:"prefer_alpha,omitempty"`
PreferAlpha *bool `protobuf:"varint,3,req,name=prefer_alpha,json=preferAlpha,def=1" json:"prefer_alpha,omitempty"`
Opus *bool `protobuf:"varint,4,opt,name=opus,def=0" json:"opus,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *CodecVersion) Reset() { *m = CodecVersion{} }
func (m *CodecVersion) String() string { return proto.CompactTextString(m) }
func (*CodecVersion) ProtoMessage() {}
func (m *CodecVersion) Reset() { *m = CodecVersion{} }
func (m *CodecVersion) String() string { return proto.CompactTextString(m) }
func (*CodecVersion) ProtoMessage() {}
func (*CodecVersion) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{21} }
const Default_CodecVersion_PreferAlpha bool = true
const Default_CodecVersion_Opus bool = false
@ -1738,30 +1787,30 @@ type UserStats struct {
// User whose stats these are.
Session *uint32 `protobuf:"varint,1,opt,name=session" json:"session,omitempty"`
// True if the message contains only mutable stats (packets, ping).
StatsOnly *bool `protobuf:"varint,2,opt,name=stats_only,def=0" json:"stats_only,omitempty"`
StatsOnly *bool `protobuf:"varint,2,opt,name=stats_only,json=statsOnly,def=0" json:"stats_only,omitempty"`
// Full user certificate chain of the user certificate in DER format.
Certificates [][]byte `protobuf:"bytes,3,rep,name=certificates" json:"certificates,omitempty"`
// Packet statistics for packets received from the client.
FromClient *UserStats_Stats `protobuf:"bytes,4,opt,name=from_client" json:"from_client,omitempty"`
FromClient *UserStats_Stats `protobuf:"bytes,4,opt,name=from_client,json=fromClient" json:"from_client,omitempty"`
// Packet statistics for packets sent by the server.
FromServer *UserStats_Stats `protobuf:"bytes,5,opt,name=from_server" json:"from_server,omitempty"`
FromServer *UserStats_Stats `protobuf:"bytes,5,opt,name=from_server,json=fromServer" json:"from_server,omitempty"`
// Amount of UDP packets sent.
UdpPackets *uint32 `protobuf:"varint,6,opt,name=udp_packets" json:"udp_packets,omitempty"`
UdpPackets *uint32 `protobuf:"varint,6,opt,name=udp_packets,json=udpPackets" json:"udp_packets,omitempty"`
// Amount of TCP packets sent.
TcpPackets *uint32 `protobuf:"varint,7,opt,name=tcp_packets" json:"tcp_packets,omitempty"`
TcpPackets *uint32 `protobuf:"varint,7,opt,name=tcp_packets,json=tcpPackets" json:"tcp_packets,omitempty"`
// UDP ping average.
UdpPingAvg *float32 `protobuf:"fixed32,8,opt,name=udp_ping_avg" json:"udp_ping_avg,omitempty"`
UdpPingAvg *float32 `protobuf:"fixed32,8,opt,name=udp_ping_avg,json=udpPingAvg" json:"udp_ping_avg,omitempty"`
// UDP ping variance.
UdpPingVar *float32 `protobuf:"fixed32,9,opt,name=udp_ping_var" json:"udp_ping_var,omitempty"`
UdpPingVar *float32 `protobuf:"fixed32,9,opt,name=udp_ping_var,json=udpPingVar" json:"udp_ping_var,omitempty"`
// TCP ping average.
TcpPingAvg *float32 `protobuf:"fixed32,10,opt,name=tcp_ping_avg" json:"tcp_ping_avg,omitempty"`
TcpPingAvg *float32 `protobuf:"fixed32,10,opt,name=tcp_ping_avg,json=tcpPingAvg" json:"tcp_ping_avg,omitempty"`
// TCP ping variance.
TcpPingVar *float32 `protobuf:"fixed32,11,opt,name=tcp_ping_var" json:"tcp_ping_var,omitempty"`
TcpPingVar *float32 `protobuf:"fixed32,11,opt,name=tcp_ping_var,json=tcpPingVar" json:"tcp_ping_var,omitempty"`
// Client version.
Version *Version `protobuf:"bytes,12,opt,name=version" json:"version,omitempty"`
// A list of CELT bitstream version constants supported by the client of this
// user.
CeltVersions []int32 `protobuf:"varint,13,rep,name=celt_versions" json:"celt_versions,omitempty"`
CeltVersions []int32 `protobuf:"varint,13,rep,name=celt_versions,json=celtVersions" json:"celt_versions,omitempty"`
// Client IP address.
Address []byte `protobuf:"bytes,14,opt,name=address" json:"address,omitempty"`
// Bandwith used by this client.
@ -1771,14 +1820,15 @@ type UserStats struct {
// Duration since last activity.
Idlesecs *uint32 `protobuf:"varint,17,opt,name=idlesecs" json:"idlesecs,omitempty"`
// True if the user has a strong certificate.
StrongCertificate *bool `protobuf:"varint,18,opt,name=strong_certificate,def=0" json:"strong_certificate,omitempty"`
StrongCertificate *bool `protobuf:"varint,18,opt,name=strong_certificate,json=strongCertificate,def=0" json:"strong_certificate,omitempty"`
Opus *bool `protobuf:"varint,19,opt,name=opus,def=0" json:"opus,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *UserStats) Reset() { *m = UserStats{} }
func (m *UserStats) String() string { return proto.CompactTextString(m) }
func (*UserStats) ProtoMessage() {}
func (m *UserStats) Reset() { *m = UserStats{} }
func (m *UserStats) String() string { return proto.CompactTextString(m) }
func (*UserStats) ProtoMessage() {}
func (*UserStats) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22} }
const Default_UserStats_StatsOnly bool = false
const Default_UserStats_StrongCertificate bool = false
@ -1929,9 +1979,10 @@ type UserStats_Stats struct {
XXX_unrecognized []byte `json:"-"`
}
func (m *UserStats_Stats) Reset() { *m = UserStats_Stats{} }
func (m *UserStats_Stats) String() string { return proto.CompactTextString(m) }
func (*UserStats_Stats) ProtoMessage() {}
func (m *UserStats_Stats) Reset() { *m = UserStats_Stats{} }
func (m *UserStats_Stats) String() string { return proto.CompactTextString(m) }
func (*UserStats_Stats) ProtoMessage() {}
func (*UserStats_Stats) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{22, 0} }
func (m *UserStats_Stats) GetGood() uint32 {
if m != nil && m.Good != nil {
@ -1971,17 +2022,18 @@ func (m *UserStats_Stats) GetResync() uint32 {
// normally be transmitted as hashes.
type RequestBlob struct {
// sessions of the requested UserState textures.
SessionTexture []uint32 `protobuf:"varint,1,rep,name=session_texture" json:"session_texture,omitempty"`
SessionTexture []uint32 `protobuf:"varint,1,rep,name=session_texture,json=sessionTexture" json:"session_texture,omitempty"`
// sessions of the requested UserState comments.
SessionComment []uint32 `protobuf:"varint,2,rep,name=session_comment" json:"session_comment,omitempty"`
SessionComment []uint32 `protobuf:"varint,2,rep,name=session_comment,json=sessionComment" json:"session_comment,omitempty"`
// channel_ids of the requested ChannelState descriptions.
ChannelDescription []uint32 `protobuf:"varint,3,rep,name=channel_description" json:"channel_description,omitempty"`
ChannelDescription []uint32 `protobuf:"varint,3,rep,name=channel_description,json=channelDescription" json:"channel_description,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *RequestBlob) Reset() { *m = RequestBlob{} }
func (m *RequestBlob) String() string { return proto.CompactTextString(m) }
func (*RequestBlob) ProtoMessage() {}
func (m *RequestBlob) Reset() { *m = RequestBlob{} }
func (m *RequestBlob) String() string { return proto.CompactTextString(m) }
func (*RequestBlob) ProtoMessage() {}
func (*RequestBlob) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{23} }
func (m *RequestBlob) GetSessionTexture() []uint32 {
if m != nil {
@ -2008,23 +2060,24 @@ func (m *RequestBlob) GetChannelDescription() []uint32 {
// details.
type ServerConfig struct {
// The maximum bandwidth the clients should use.
MaxBandwidth *uint32 `protobuf:"varint,1,opt,name=max_bandwidth" json:"max_bandwidth,omitempty"`
MaxBandwidth *uint32 `protobuf:"varint,1,opt,name=max_bandwidth,json=maxBandwidth" json:"max_bandwidth,omitempty"`
// Server welcome text.
WelcomeText *string `protobuf:"bytes,2,opt,name=welcome_text" json:"welcome_text,omitempty"`
WelcomeText *string `protobuf:"bytes,2,opt,name=welcome_text,json=welcomeText" json:"welcome_text,omitempty"`
// True if the server allows HTML.
AllowHtml *bool `protobuf:"varint,3,opt,name=allow_html" json:"allow_html,omitempty"`
AllowHtml *bool `protobuf:"varint,3,opt,name=allow_html,json=allowHtml" json:"allow_html,omitempty"`
// Maximum text message length.
MessageLength *uint32 `protobuf:"varint,4,opt,name=message_length" json:"message_length,omitempty"`
MessageLength *uint32 `protobuf:"varint,4,opt,name=message_length,json=messageLength" json:"message_length,omitempty"`
// Maximum image message length.
ImageMessageLength *uint32 `protobuf:"varint,5,opt,name=image_message_length" json:"image_message_length,omitempty"`
ImageMessageLength *uint32 `protobuf:"varint,5,opt,name=image_message_length,json=imageMessageLength" json:"image_message_length,omitempty"`
// The maximum number of users allowed on the server.
MaxUsers *uint32 `protobuf:"varint,6,opt,name=max_users" json:"max_users,omitempty"`
MaxUsers *uint32 `protobuf:"varint,6,opt,name=max_users,json=maxUsers" json:"max_users,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *ServerConfig) Reset() { *m = ServerConfig{} }
func (m *ServerConfig) String() string { return proto.CompactTextString(m) }
func (*ServerConfig) ProtoMessage() {}
func (m *ServerConfig) Reset() { *m = ServerConfig{} }
func (m *ServerConfig) String() string { return proto.CompactTextString(m) }
func (*ServerConfig) ProtoMessage() {}
func (*ServerConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{24} }
func (m *ServerConfig) GetMaxBandwidth() uint32 {
if m != nil && m.MaxBandwidth != nil {
@ -2077,13 +2130,14 @@ type SuggestConfig struct {
// server.
Positional *bool `protobuf:"varint,2,opt,name=positional" json:"positional,omitempty"`
// True if the administrator suggests push to talk to be used on this server.
PushToTalk *bool `protobuf:"varint,3,opt,name=push_to_talk" json:"push_to_talk,omitempty"`
PushToTalk *bool `protobuf:"varint,3,opt,name=push_to_talk,json=pushToTalk" json:"push_to_talk,omitempty"`
XXX_unrecognized []byte `json:"-"`
}
func (m *SuggestConfig) Reset() { *m = SuggestConfig{} }
func (m *SuggestConfig) String() string { return proto.CompactTextString(m) }
func (*SuggestConfig) ProtoMessage() {}
func (m *SuggestConfig) Reset() { *m = SuggestConfig{} }
func (m *SuggestConfig) String() string { return proto.CompactTextString(m) }
func (*SuggestConfig) ProtoMessage() {}
func (*SuggestConfig) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{25} }
func (m *SuggestConfig) GetVersion() uint32 {
if m != nil && m.Version != nil {
@ -2107,8 +2161,198 @@ func (m *SuggestConfig) GetPushToTalk() bool {
}
func init() {
proto.RegisterType((*Version)(nil), "MumbleProto.Version")
proto.RegisterType((*UDPTunnel)(nil), "MumbleProto.UDPTunnel")
proto.RegisterType((*Authenticate)(nil), "MumbleProto.Authenticate")
proto.RegisterType((*Ping)(nil), "MumbleProto.Ping")
proto.RegisterType((*Reject)(nil), "MumbleProto.Reject")
proto.RegisterType((*ServerSync)(nil), "MumbleProto.ServerSync")
proto.RegisterType((*ChannelRemove)(nil), "MumbleProto.ChannelRemove")
proto.RegisterType((*ChannelState)(nil), "MumbleProto.ChannelState")
proto.RegisterType((*UserRemove)(nil), "MumbleProto.UserRemove")
proto.RegisterType((*UserState)(nil), "MumbleProto.UserState")
proto.RegisterType((*BanList)(nil), "MumbleProto.BanList")
proto.RegisterType((*BanList_BanEntry)(nil), "MumbleProto.BanList.BanEntry")
proto.RegisterType((*TextMessage)(nil), "MumbleProto.TextMessage")
proto.RegisterType((*PermissionDenied)(nil), "MumbleProto.PermissionDenied")
proto.RegisterType((*ACL)(nil), "MumbleProto.ACL")
proto.RegisterType((*ACL_ChanGroup)(nil), "MumbleProto.ACL.ChanGroup")
proto.RegisterType((*ACL_ChanACL)(nil), "MumbleProto.ACL.ChanACL")
proto.RegisterType((*QueryUsers)(nil), "MumbleProto.QueryUsers")
proto.RegisterType((*CryptSetup)(nil), "MumbleProto.CryptSetup")
proto.RegisterType((*ContextActionModify)(nil), "MumbleProto.ContextActionModify")
proto.RegisterType((*ContextAction)(nil), "MumbleProto.ContextAction")
proto.RegisterType((*UserList)(nil), "MumbleProto.UserList")
proto.RegisterType((*UserList_User)(nil), "MumbleProto.UserList.User")
proto.RegisterType((*VoiceTarget)(nil), "MumbleProto.VoiceTarget")
proto.RegisterType((*VoiceTarget_Target)(nil), "MumbleProto.VoiceTarget.Target")
proto.RegisterType((*PermissionQuery)(nil), "MumbleProto.PermissionQuery")
proto.RegisterType((*CodecVersion)(nil), "MumbleProto.CodecVersion")
proto.RegisterType((*UserStats)(nil), "MumbleProto.UserStats")
proto.RegisterType((*UserStats_Stats)(nil), "MumbleProto.UserStats.Stats")
proto.RegisterType((*RequestBlob)(nil), "MumbleProto.RequestBlob")
proto.RegisterType((*ServerConfig)(nil), "MumbleProto.ServerConfig")
proto.RegisterType((*SuggestConfig)(nil), "MumbleProto.SuggestConfig")
proto.RegisterEnum("MumbleProto.Reject_RejectType", Reject_RejectType_name, Reject_RejectType_value)
proto.RegisterEnum("MumbleProto.PermissionDenied_DenyType", PermissionDenied_DenyType_name, PermissionDenied_DenyType_value)
proto.RegisterEnum("MumbleProto.ContextActionModify_Context", ContextActionModify_Context_name, ContextActionModify_Context_value)
proto.RegisterEnum("MumbleProto.ContextActionModify_Operation", ContextActionModify_Operation_name, ContextActionModify_Operation_value)
}
func init() { proto.RegisterFile("Mumble.proto", fileDescriptor0) }
var fileDescriptor0 = []byte{
// 2418 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xdc, 0x58, 0x4b, 0x73, 0x23, 0x49,
0x11, 0xa6, 0xf5, 0xb2, 0x94, 0x92, 0x6c, 0xb9, 0x67, 0x58, 0x84, 0xf7, 0xdd, 0x0b, 0xcb, 0x00,
0x1b, 0x66, 0x71, 0xec, 0x65, 0x27, 0x82, 0x83, 0xc7, 0xc3, 0xe2, 0x09, 0xc6, 0x5e, 0xd3, 0xf6,
0xce, 0x1e, 0x38, 0x34, 0x6d, 0x75, 0x59, 0x6a, 0xdc, 0xea, 0x6e, 0xba, 0x5a, 0x9e, 0x55, 0x04,
0x47, 0xe0, 0x0a, 0x11, 0x1c, 0xb8, 0xf1, 0x03, 0x08, 0x62, 0x23, 0xf8, 0x01, 0x5c, 0xf8, 0x05,
0xfc, 0x01, 0x2e, 0x5c, 0xb9, 0x11, 0xc1, 0x9d, 0x7c, 0x54, 0xbf, 0x6c, 0xcd, 0xce, 0x72, 0xe5,
0x22, 0x55, 0x7e, 0x99, 0x5d, 0x95, 0x95, 0x95, 0xaf, 0x2a, 0x18, 0x9d, 0xac, 0x96, 0x97, 0x91,
0xda, 0x4f, 0xb3, 0x24, 0x4f, 0xec, 0xa1, 0x50, 0x67, 0x44, 0x38, 0x11, 0x6c, 0x3d, 0x53, 0x99,
0x0e, 0x93, 0xd8, 0x9e, 0xc2, 0xd6, 0x8d, 0x0c, 0xa7, 0xd6, 0x5b, 0xd6, 0x83, 0xb1, 0x5b, 0x90,
0xc4, 0xc9, 0x54, 0xa4, 0x7c, 0xad, 0xa6, 0x2d, 0xe4, 0x0c, 0xdc, 0x82, 0xb4, 0xb7, 0xa1, 0x95,
0xe8, 0x69, 0x9b, 0x41, 0x1c, 0xd9, 0xaf, 0x03, 0x24, 0xda, 0x2b, 0xa6, 0xe9, 0x30, 0x3e, 0x48,
0xb4, 0x59, 0xc2, 0x79, 0x07, 0x06, 0x9f, 0x3c, 0x3e, 0xbb, 0x58, 0xc5, 0xb1, 0x8a, 0xec, 0x57,
0xa0, 0x97, 0xfa, 0xb3, 0x6b, 0x95, 0xe3, 0x72, 0xad, 0x07, 0x23, 0xd7, 0x50, 0xce, 0x1f, 0x2d,
0x18, 0x1d, 0xae, 0xf2, 0x85, 0x8a, 0xf3, 0x70, 0xe6, 0xe7, 0xca, 0xde, 0x83, 0xfe, 0x4a, 0xab,
0x2c, 0xf6, 0x97, 0x8a, 0x35, 0x1b, 0xb8, 0x25, 0x4d, 0xbc, 0xd4, 0xd7, 0xfa, 0x79, 0x92, 0x05,
0x46, 0xb7, 0x92, 0xa6, 0x05, 0xf2, 0xe4, 0x5a, 0xc5, 0xa4, 0x60, 0x1b, 0x39, 0x86, 0xb2, 0xdf,
0x81, 0xf1, 0x4c, 0x45, 0x79, 0xa1, 0xa6, 0x46, 0x3d, 0xdb, 0x0f, 0xba, 0xee, 0x88, 0x40, 0xa3,
0xa9, 0xb6, 0xbf, 0x0e, 0x9d, 0x24, 0x5d, 0xe9, 0x69, 0x17, 0x27, 0xed, 0x3f, 0xec, 0x5e, 0xf9,
0x91, 0x56, 0x2e, 0x43, 0xce, 0xdf, 0x5a, 0xd0, 0x39, 0x0b, 0xe3, 0xb9, 0xfd, 0x1a, 0x0c, 0xf2,
0x70, 0xa9, 0x74, 0xee, 0x2f, 0x53, 0xd6, 0xac, 0xe3, 0x56, 0x80, 0x6d, 0x43, 0x67, 0x9e, 0x24,
0xa2, 0xd6, 0xd8, 0xe5, 0x31, 0x61, 0x11, 0x6e, 0x89, 0x2d, 0x86, 0x18, 0x8d, 0x19, 0x4b, 0x74,
0xce, 0xd6, 0x22, 0x0c, 0xc7, 0xa4, 0x7a, 0xa6, 0xf4, 0x3a, 0x9e, 0xf1, 0xfa, 0x63, 0xd7, 0x50,
0xf6, 0x9b, 0x30, 0x5c, 0x05, 0xa9, 0x27, 0x96, 0xd2, 0xd3, 0x1e, 0x33, 0x01, 0xa1, 0x33, 0x41,
0x48, 0x20, 0x9f, 0x55, 0x02, 0x5b, 0x22, 0x80, 0x50, 0x21, 0xf0, 0x16, 0x8c, 0x78, 0x06, 0xd4,
0xdf, 0xf3, 0x6f, 0xe6, 0xd3, 0x3e, 0x4a, 0xb4, 0x64, 0x0a, 0x84, 0x0e, 0x6f, 0xe6, 0x0d, 0x89,
0x1b, 0x3f, 0x9b, 0x0e, 0x1a, 0x12, 0xcf, 0xfc, 0x8c, 0x24, 0x78, 0x91, 0x62, 0x0e, 0x10, 0x09,
0x5a, 0xa5, 0x9a, 0xa3, 0x94, 0xa0, 0x39, 0x86, 0x0d, 0x09, 0x9c, 0xc3, 0xf9, 0x75, 0x0b, 0x7a,
0xae, 0xfa, 0xb9, 0x9a, 0xe5, 0xf6, 0x01, 0x74, 0xf2, 0x75, 0x2a, 0x67, 0xbb, 0x7d, 0xf0, 0xc6,
0x7e, 0xcd, 0x3f, 0xf7, 0x45, 0xc4, 0xfc, 0x5d, 0xa0, 0x94, 0xcb, 0xb2, 0x62, 0x20, 0x5f, 0xa3,
0x93, 0xc9, 0xa9, 0x1b, 0xca, 0xf9, 0xdc, 0x02, 0xa8, 0x84, 0xed, 0x3e, 0x74, 0x4e, 0x93, 0x58,
0x4d, 0xbe, 0x62, 0x4f, 0x60, 0xf4, 0x69, 0x96, 0xe0, 0xda, 0x72, 0xc0, 0x13, 0xcb, 0xbe, 0x07,
0x3b, 0x4f, 0xe2, 0x1b, 0x3f, 0x0a, 0x83, 0x4f, 0x8c, 0x37, 0x4d, 0x5a, 0xf6, 0x0e, 0x0c, 0x59,
0x8c, 0xa0, 0xb3, 0x4f, 0x27, 0x6d, 0x7b, 0x17, 0xc6, 0x0c, 0x9c, 0xab, 0xec, 0x86, 0xa1, 0x0e,
0x41, 0xc5, 0x17, 0x4f, 0x62, 0x1c, 0x4d, 0xba, 0x18, 0x07, 0x20, 0x02, 0x1f, 0xad, 0xa2, 0x68,
0xd2, 0x23, 0x91, 0xd3, 0xe4, 0x48, 0x65, 0x79, 0x78, 0xc5, 0x3e, 0x3c, 0xd9, 0xb2, 0xbf, 0x0a,
0xbb, 0x35, 0xaf, 0x4e, 0xb2, 0x8f, 0xfc, 0x30, 0x9a, 0xf4, 0x9d, 0xdf, 0x59, 0xc5, 0xa7, 0xe7,
0x74, 0xc0, 0x18, 0x6a, 0x5a, 0xe9, 0x7a, 0x10, 0x1a, 0x92, 0xbc, 0x76, 0xe9, 0x7f, 0xe6, 0x5d,
0xfa, 0x71, 0xf0, 0x3c, 0x0c, 0xf2, 0x85, 0xf1, 0xab, 0x11, 0x82, 0x8f, 0x0a, 0xcc, 0x7e, 0x1b,
0x46, 0xcf, 0x55, 0x34, 0x4b, 0x96, 0xca, 0xcb, 0xd5, 0x67, 0xb9, 0x89, 0xcc, 0xa1, 0xc1, 0x2e,
0x10, 0xc2, 0xa3, 0x19, 0xa6, 0x2a, 0x5b, 0x86, 0xba, 0xf0, 0x7d, 0x72, 0xdb, 0x3a, 0xe4, 0xec,
0xc3, 0xf8, 0x68, 0xe1, 0x53, 0x8c, 0xba, 0x6a, 0x99, 0xdc, 0x28, 0x8a, 0xea, 0x99, 0x00, 0x5e,
0x18, 0x70, 0xb4, 0x8e, 0xdd, 0x81, 0x41, 0x9e, 0x04, 0xce, 0x3f, 0x5a, 0x30, 0x32, 0x1f, 0x9c,
0xe7, 0xe4, 0xd1, 0xb7, 0xe5, 0xad, 0x86, 0xbc, 0x04, 0x7e, 0x86, 0x86, 0x30, 0x5b, 0x30, 0x14,
0x05, 0x02, 0xc7, 0xb8, 0x28, 0xcd, 0x63, 0xfb, 0x3e, 0x74, 0xa3, 0x30, 0xbe, 0x96, 0x18, 0x1d,
0xbb, 0x42, 0xd0, 0x1e, 0x02, 0xa5, 0x67, 0x59, 0x98, 0xe6, 0x64, 0xa9, 0xae, 0xec, 0xb2, 0x06,
0xd9, 0xaf, 0xc2, 0x80, 0x45, 0x3d, 0x3f, 0x08, 0x30, 0x4c, 0xe8, 0xdb, 0x3e, 0x03, 0x87, 0x41,
0x40, 0x56, 0x12, 0x66, 0xc6, 0xfb, 0xc3, 0x28, 0x21, 0xfe, 0x90, 0x31, 0xb3, 0x65, 0xcc, 0x54,
0xb9, 0x5a, 0xa6, 0x49, 0xe6, 0x67, 0x6b, 0x8e, 0x91, 0x32, 0x07, 0x54, 0x38, 0xee, 0xb3, 0x9f,
0x26, 0x3a, 0x64, 0x1d, 0x28, 0x4a, 0xba, 0x0f, 0xad, 0xf7, 0xdd, 0x12, 0xb2, 0xbf, 0x0d, 0x93,
0x9a, 0x4a, 0xde, 0xc2, 0xd7, 0x0b, 0x0e, 0x95, 0x91, 0xbb, 0x53, 0xc3, 0x8f, 0x11, 0x26, 0x75,
0xe9, 0x70, 0x29, 0xad, 0x69, 0x0e, 0x16, 0x54, 0x17, 0x01, 0x72, 0x33, 0xed, 0x5c, 0x01, 0xd0,
0xc0, 0x68, 0xd6, 0xf0, 0x90, 0x56, 0xdd, 0x43, 0xd0, 0x56, 0xfe, 0x0c, 0x3d, 0xcb, 0x98, 0x55,
0x88, 0x5a, 0xa4, 0xb4, 0xeb, 0x91, 0x82, 0x01, 0xd1, 0x46, 0x5f, 0xe2, 0xf3, 0xef, 0xbb, 0x34,
0x74, 0xfe, 0xdc, 0xc1, 0xf4, 0x8c, 0x0b, 0xc9, 0x21, 0xbe, 0xd8, 0x13, 0x37, 0xaf, 0xb3, 0xe9,
0xf4, 0xbe, 0x06, 0x5b, 0xb4, 0x25, 0xf2, 0x02, 0xc9, 0x6e, 0x3d, 0x22, 0xd1, 0x05, 0x9a, 0x1e,
0xd2, 0xbd, 0xed, 0x21, 0x38, 0xd7, 0x72, 0x85, 0x69, 0xb2, 0xc7, 0xca, 0xf1, 0x98, 0xb0, 0x40,
0xf9, 0x57, 0x9c, 0xd2, 0x10, 0xa3, 0x31, 0x65, 0x7f, 0xbd, 0x4a, 0x53, 0x4c, 0x8e, 0x5a, 0x0e,
0xc9, 0x2d, 0x69, 0x32, 0xa9, 0x56, 0xd1, 0x95, 0xc7, 0x13, 0x0d, 0x0c, 0x13, 0x81, 0x13, 0x9a,
0xac, 0x60, 0xf2, 0x8c, 0x50, 0x31, 0x1f, 0xd3, 0xac, 0xb8, 0x73, 0x0a, 0x9e, 0x55, 0xa6, 0xf8,
0x28, 0x46, 0x6e, 0x41, 0xda, 0xdf, 0x84, 0xed, 0x34, 0x5a, 0xcd, 0xc3, 0xd8, 0x9b, 0x25, 0x31,
0x07, 0xd8, 0x88, 0x05, 0xc6, 0x82, 0x1e, 0x09, 0x68, 0x7f, 0x0b, 0x76, 0x8c, 0x58, 0x18, 0x50,
0xbc, 0xe7, 0xeb, 0xe9, 0x98, 0xad, 0x62, 0xbe, 0x7e, 0x62, 0x50, 0x5a, 0x09, 0xe3, 0x72, 0x49,
0xa1, 0xb0, 0x2d, 0x85, 0xd5, 0x90, 0xb4, 0x5b, 0xf6, 0x97, 0x1d, 0xb1, 0x26, 0x8d, 0xc9, 0x6d,
0x0d, 0x5b, 0x7c, 0x69, 0xc2, 0x6b, 0x0f, 0x0d, 0x76, 0x6c, 0x44, 0x8c, 0xae, 0x22, 0xb2, 0x2b,
0x22, 0x06, 0x63, 0x11, 0xf4, 0xca, 0x34, 0x0b, 0x93, 0x0c, 0xd7, 0xf7, 0x74, 0xaa, 0xfc, 0x6b,
0x95, 0x4d, 0x6d, 0xb6, 0xc0, 0x4e, 0x81, 0x9f, 0x0b, 0x4c, 0xf5, 0x2d, 0x53, 0x33, 0x2c, 0xa5,
0x98, 0xb3, 0xa7, 0xf7, 0x58, 0xa6, 0x02, 0x9c, 0xdf, 0xb4, 0x60, 0x0b, 0x33, 0xcf, 0xd3, 0x10,
0xeb, 0xd5, 0xf7, 0xa1, 0x83, 0x1e, 0xa4, 0xd1, 0x53, 0xda, 0x0f, 0x86, 0x07, 0xaf, 0x37, 0x52,
0xb8, 0x91, 0xa1, 0xff, 0x1f, 0xc6, 0x79, 0xb6, 0x76, 0x59, 0x14, 0x8f, 0xa0, 0xfb, 0x8b, 0x95,
0xc2, 0xe8, 0x6a, 0xd5, 0xa3, 0x4b, 0xb0, 0xbd, 0x3f, 0x59, 0xd0, 0x2f, 0xe4, 0xc9, 0x4a, 0x18,
0xc5, 0x7c, 0xc8, 0xd2, 0x29, 0x14, 0x24, 0xfb, 0x89, 0xaf, 0xaf, 0x71, 0x0a, 0x0a, 0x04, 0x1e,
0x6f, 0xf4, 0xc3, 0xc2, 0x9a, 0x9d, 0x9a, 0x35, 0xab, 0xb8, 0xe8, 0x36, 0xe2, 0x02, 0xbd, 0x1b,
0xeb, 0x77, 0x96, 0xb3, 0xf3, 0x0d, 0x5c, 0x21, 0xc8, 0xd3, 0x82, 0x55, 0xe6, 0x73, 0xa8, 0x4b,
0x51, 0x2d, 0x69, 0xe7, 0xb7, 0x16, 0x0c, 0x29, 0xb5, 0x9e, 0xa0, 0x4a, 0xfe, 0x5c, 0x55, 0xf1,
0x61, 0xd5, 0xe3, 0xa3, 0x16, 0x4f, 0x2d, 0xce, 0x37, 0x65, 0x3c, 0x35, 0x83, 0xa1, 0xcd, 0xcc,
0x5a, 0x30, 0x60, 0x10, 0xe5, 0x99, 0x52, 0x12, 0x44, 0xc4, 0xeb, 0x11, 0x89, 0x0c, 0x9c, 0x71,
0x29, 0x4b, 0xe2, 0x16, 0x5a, 0xe4, 0x3d, 0x86, 0x74, 0x7e, 0xdf, 0x86, 0xc9, 0x59, 0x99, 0xd1,
0x1f, 0xab, 0x38, 0x54, 0x81, 0xfd, 0x06, 0x40, 0x95, 0xe5, 0x8d, 0x6e, 0x35, 0xe4, 0x96, 0x1a,
0xad, 0xdb, 0x31, 0x59, 0xd3, 0xbf, 0xdd, 0xcc, 0x07, 0x95, 0x25, 0x3b, 0x0d, 0x4b, 0x3e, 0x34,
0x75, 0xbd, 0xcb, 0x75, 0xfd, 0xdd, 0x86, 0x53, 0xdc, 0xd6, 0x6e, 0x1f, 0xff, 0xd6, 0xb5, 0xfa,
0x5e, 0x9c, 0x62, 0xaf, 0x3a, 0x45, 0xe7, 0xaf, 0xe8, 0x14, 0x85, 0x18, 0x55, 0x76, 0xb2, 0x39,
0x56, 0x76, 0xac, 0xbd, 0xd5, 0x6c, 0x58, 0xd7, 0xc7, 0x30, 0x38, 0x5f, 0xe1, 0xbe, 0x28, 0x95,
0x49, 0x45, 0x37, 0xc5, 0xe9, 0x94, 0x4a, 0x7c, 0x9b, 0x00, 0xfa, 0xf2, 0x22, 0x49, 0x9e, 0x62,
0x5d, 0xc7, 0x7a, 0xbe, 0x05, 0xed, 0xe3, 0x0f, 0x7f, 0x8c, 0x55, 0xfc, 0x3e, 0x4c, 0x2e, 0x8a,
0xe4, 0x6e, 0xbe, 0xc1, 0x5a, 0xfe, 0x0a, 0xd8, 0x27, 0x34, 0x79, 0x3c, 0x6f, 0x16, 0xf4, 0x11,
0xf4, 0x69, 0x09, 0x9e, 0xb5, 0x5f, 0x5b, 0x86, 0x5b, 0x80, 0x01, 0x35, 0x1c, 0xa7, 0xd8, 0x09,
0xe2, 0x67, 0x4f, 0xc3, 0x65, 0x98, 0x4f, 0xc0, 0xf9, 0x55, 0x17, 0xda, 0x87, 0x47, 0x4f, 0x5f,
0x52, 0x4e, 0x31, 0x7b, 0x8c, 0xc2, 0x78, 0xa1, 0x30, 0x10, 0x3d, 0x7f, 0x16, 0x69, 0x13, 0x1f,
0x9d, 0x3c, 0x5b, 0x29, 0x77, 0x68, 0x38, 0x87, 0xc8, 0xc0, 0xbe, 0xa9, 0x37, 0xcf, 0x92, 0x55,
0x2a, 0xfd, 0xed, 0xf0, 0x60, 0xaf, 0x61, 0x61, 0x5c, 0x69, 0x9f, 0x34, 0xfa, 0x11, 0x89, 0xb8,
0x46, 0xd2, 0x7e, 0x0f, 0x3a, 0x3c, 0x69, 0x87, 0xbf, 0x98, 0x6e, 0xfc, 0x02, 0xff, 0x5d, 0x96,
0xaa, 0x62, 0xb4, 0xbb, 0x21, 0x46, 0xff, 0x69, 0xc1, 0xa0, 0x5c, 0xa0, 0x3c, 0x30, 0x8b, 0x3d,
0x51, 0xc2, 0xce, 0x81, 0x81, 0xd1, 0x57, 0x05, 0x8d, 0x6d, 0x54, 0x30, 0x7a, 0xe5, 0x96, 0x21,
0xd8, 0xad, 0x0a, 0x89, 0x02, 0xb4, 0xdf, 0x85, 0x62, 0xcf, 0x3e, 0x2a, 0x2a, 0xe5, 0xea, 0x96,
0x31, 0x88, 0x41, 0xe5, 0x8c, 0x4a, 0x7d, 0x97, 0x23, 0x84, 0x86, 0xe2, 0x96, 0x5c, 0xdf, 0xa5,
0xfe, 0x1b, 0xca, 0xfe, 0x2e, 0xec, 0x96, 0xcb, 0x7b, 0x4b, 0xb5, 0xbc, 0xa4, 0x9a, 0x2b, 0x2d,
0xc0, 0xa4, 0x64, 0x9c, 0x08, 0xbe, 0xf7, 0x77, 0x0b, 0xb6, 0x8c, 0x4d, 0xb0, 0x27, 0x00, 0x3f,
0x4d, 0xa3, 0xb5, 0x87, 0x32, 0xd2, 0xad, 0x96, 0xfb, 0x61, 0xfc, 0x18, 0xe1, 0x4a, 0x48, 0xaf,
0x2e, 0x9b, 0x67, 0x27, 0x42, 0xe7, 0x08, 0x37, 0x0d, 0xd3, 0xde, 0x6c, 0x98, 0x17, 0xd6, 0x4e,
0x4c, 0x2f, 0x7c, 0x98, 0x26, 0x6f, 0x09, 0x21, 0xa8, 0x1f, 0xe7, 0xe6, 0x4e, 0x20, 0x84, 0x14,
0xcd, 0x78, 0x6d, 0x52, 0x16, 0x8f, 0x9d, 0x0f, 0x00, 0x7e, 0x42, 0x07, 0xc8, 0xcd, 0x05, 0xd9,
0x2d, 0x0c, 0x24, 0x71, 0xa3, 0xdd, 0x70, 0x48, 0x33, 0xd1, 0xe9, 0x69, 0x4e, 0x53, 0x38, 0x3f,
0x13, 0x4e, 0x00, 0x70, 0x94, 0xad, 0xd3, 0xfc, 0x5c, 0xe5, 0xb8, 0x1a, 0x7e, 0x75, 0xad, 0xd6,
0x6c, 0x83, 0x91, 0x4b, 0x43, 0x2e, 0x4e, 0x51, 0x48, 0xb5, 0x29, 0x4e, 0xe2, 0x99, 0x5c, 0x14,
0xa9, 0x38, 0x31, 0x76, 0x4a, 0x10, 0x89, 0x68, 0xee, 0x74, 0x8d, 0x48, 0x5b, 0x44, 0x04, 0x63,
0x11, 0xe7, 0x3f, 0x16, 0xdc, 0x33, 0x55, 0xf4, 0x70, 0x46, 0xc9, 0xf5, 0x24, 0x09, 0xc2, 0xab,
0x35, 0x9d, 0xa5, 0xcf, 0xb4, 0xf1, 0x2f, 0x43, 0xd1, 0xfe, 0xb8, 0x0c, 0xcb, 0x25, 0x80, 0xc7,
0x52, 0x54, 0xe3, 0xb2, 0xfd, 0x1d, 0xbb, 0x05, 0x69, 0x1f, 0xc3, 0x20, 0xc1, 0xc4, 0x20, 0x59,
0xbc, 0xc3, 0x59, 0xe9, 0x3b, 0x8d, 0x08, 0xd8, 0xb0, 0xf4, 0xfe, 0xc7, 0xc5, 0x17, 0x6e, 0xf5,
0xb1, 0xf3, 0x1e, 0x7a, 0x85, 0x99, 0x14, 0xa0, 0x27, 0xfd, 0x3b, 0xa6, 0x9e, 0xa1, 0x38, 0x0b,
0xe5, 0x8d, 0x16, 0x65, 0x28, 0x4e, 0x41, 0x1d, 0xe7, 0x2d, 0x18, 0x94, 0xb3, 0x50, 0xb6, 0xc1,
0x1e, 0x14, 0xf3, 0x16, 0xd0, 0x05, 0x88, 0x3c, 0x72, 0x62, 0x39, 0x3f, 0xc3, 0x96, 0xbb, 0xbe,
0xf6, 0x17, 0x74, 0x5f, 0x2f, 0x49, 0xd3, 0x95, 0xa5, 0xda, 0x75, 0x4b, 0x39, 0x7f, 0xb1, 0x24,
0x5d, 0x71, 0xb9, 0x7e, 0x1f, 0xba, 0xd2, 0x6a, 0x5a, 0x1b, 0x12, 0x47, 0x21, 0xc5, 0x03, 0x57,
0x04, 0xf7, 0xb4, 0x6c, 0xa6, 0xee, 0x95, 0x92, 0xb8, 0x0a, 0xaf, 0x2c, 0xe2, 0xbf, 0x55, 0x2b,
0xbb, 0xd4, 0x84, 0xfb, 0x3a, 0xf7, 0xb4, 0x52, 0x45, 0xf7, 0xd9, 0x27, 0xe0, 0x1c, 0x69, 0x6e,
0xc2, 0x89, 0x69, 0x54, 0x37, 0x4e, 0x3e, 0x24, 0xcc, 0xd8, 0xd0, 0xf9, 0x37, 0x16, 0xd6, 0x67,
0x49, 0x38, 0x53, 0x17, 0x7e, 0x36, 0x57, 0x39, 0xbd, 0x36, 0x94, 0xf7, 0x09, 0x1c, 0xd9, 0x1f,
0x62, 0x65, 0x64, 0x8e, 0xf8, 0xea, 0xf0, 0xe0, 0xcd, 0xc6, 0x46, 0x6a, 0x9f, 0xee, 0xcb, 0x9f,
0x5b, 0xc8, 0xef, 0xfd, 0xc1, 0x82, 0x9e, 0x99, 0xb5, 0x61, 0xea, 0xf6, 0xff, 0x60, 0xea, 0x32,
0x10, 0xdb, 0xf5, 0x40, 0x7c, 0xb5, 0xba, 0xb1, 0xd4, 0x73, 0xa6, 0x5c, 0x5c, 0xde, 0x86, 0xfe,
0x6c, 0x11, 0x46, 0xd8, 0xbd, 0xc4, 0xcd, 0x9c, 0x5a, 0xc2, 0x4e, 0x02, 0x3b, 0x55, 0x39, 0xe3,
0x40, 0x7d, 0xd9, 0x7d, 0xea, 0xd6, 0x8d, 0x4e, 0xf4, 0xac, 0x43, 0xa4, 0xd3, 0x55, 0xb4, 0xc2,
0x06, 0xa8, 0xdd, 0xd0, 0x89, 0x31, 0xe7, 0x97, 0x78, 0x7b, 0x4b, 0x02, 0x35, 0x2b, 0xde, 0x81,
0xa8, 0x7d, 0x89, 0xd2, 0x85, 0xcf, 0x07, 0xdc, 0x75, 0x85, 0xa0, 0xf3, 0xbd, 0x54, 0xb9, 0xcf,
0xad, 0x56, 0xd7, 0xe5, 0x31, 0x55, 0x2a, 0xec, 0xb5, 0xaf, 0xd0, 0x1d, 0xe4, 0x03, 0xf2, 0xb8,
0x32, 0x39, 0x0b, 0xe7, 0x90, 0x3f, 0x2e, 0x1e, 0x53, 0x3a, 0x77, 0x1f, 0x53, 0x3e, 0xef, 0x55,
0x97, 0x0e, 0xfd, 0x05, 0x6e, 0xff, 0x0d, 0x00, 0x4d, 0x22, 0x5e, 0x12, 0x47, 0xb7, 0x7a, 0xc6,
0x01, 0x33, 0x3e, 0x46, 0x1c, 0x13, 0xeb, 0x68, 0x56, 0x15, 0x69, 0x29, 0x8c, 0x23, 0xb7, 0x81,
0xd9, 0x3f, 0x80, 0xe1, 0x55, 0x96, 0x2c, 0x3d, 0x49, 0x4d, 0xac, 0xd3, 0xf0, 0xe0, 0xb5, 0x3b,
0x21, 0xc0, 0x0a, 0xed, 0xf3, 0xaf, 0x0b, 0xf4, 0xc1, 0x11, 0xcb, 0x97, 0x9f, 0x4b, 0xda, 0xe2,
0x53, 0xfc, 0x52, 0x9f, 0x4b, 0x92, 0xf8, 0xff, 0x79, 0xc1, 0xb1, 0xf7, 0xab, 0xf7, 0xc2, 0x11,
0x1b, 0xe1, 0x7e, 0x33, 0xfa, 0x84, 0x57, 0xbd, 0x22, 0xde, 0x79, 0x76, 0x1b, 0x6f, 0x78, 0x76,
0xab, 0xf5, 0xfa, 0xdb, 0x72, 0xf7, 0x2a, 0x7a, 0x7d, 0xbc, 0x8c, 0x54, 0x6f, 0x1f, 0x3b, 0x12,
0x03, 0x25, 0x40, 0xcd, 0x2d, 0x3a, 0x46, 0x18, 0x2b, 0xad, 0x66, 0x9a, 0x6f, 0x46, 0x68, 0xb4,
0x0a, 0xa1, 0xfe, 0x3d, 0x0c, 0x22, 0xe1, 0xee, 0x4a, 0xff, 0x5e, 0xd0, 0xf6, 0x07, 0x60, 0xeb,
0x9c, 0xde, 0x78, 0xbc, 0x9a, 0x9f, 0xc8, 0x9d, 0xa8, 0x70, 0xb1, 0x5d, 0x11, 0xa8, 0x35, 0x80,
0xa5, 0x4f, 0xdf, 0xbb, 0xe3, 0xd3, 0x7b, 0x3f, 0x85, 0xae, 0xb8, 0x73, 0xf1, 0x04, 0x68, 0x6d,
0x78, 0x02, 0x6c, 0x6d, 0x78, 0x02, 0x6c, 0x6f, 0x7c, 0x02, 0xec, 0xd4, 0x9f, 0x00, 0xe9, 0xc1,
0x68, 0xe8, 0x2a, 0x6c, 0xc1, 0x74, 0xfe, 0x28, 0x4a, 0x2e, 0xe9, 0xb2, 0x69, 0x62, 0xc4, 0x2b,
0x6e, 0xad, 0x92, 0xc6, 0xb6, 0x0d, 0x7c, 0x61, 0x2e, 0xaf, 0x35, 0xc1, 0xe2, 0xd2, 0xd9, 0x6a,
0x08, 0x1e, 0x99, 0xbb, 0xe7, 0xf7, 0xe0, 0x5e, 0x91, 0x6e, 0xea, 0xaf, 0x2c, 0x72, 0x31, 0xb1,
0x0d, 0xeb, 0x71, 0xc5, 0x71, 0xfe, 0x65, 0xc1, 0x48, 0xdc, 0x1b, 0x8b, 0xd8, 0x55, 0x38, 0xbf,
0xfb, 0x56, 0x65, 0x7d, 0x89, 0xb7, 0xaa, 0xd6, 0xdd, 0xb7, 0x2a, 0x4c, 0x7c, 0x7e, 0x14, 0x25,
0xcf, 0xbd, 0x45, 0xbe, 0x8c, 0x24, 0x79, 0x61, 0x1b, 0x45, 0xc8, 0x31, 0x02, 0x74, 0x1d, 0x37,
0x37, 0x1e, 0x2f, 0x52, 0xf1, 0x3c, 0x5f, 0x18, 0x53, 0x8d, 0x0d, 0xfa, 0x94, 0x41, 0xac, 0x76,
0xf7, 0xc3, 0x25, 0x09, 0xdd, 0x12, 0x96, 0x67, 0x07, 0x9b, 0x79, 0x27, 0x8d, 0x2f, 0x1a, 0xcf,
0x31, 0xbd, 0x5b, 0xcf, 0x31, 0xd7, 0x30, 0x3e, 0x5f, 0xcd, 0xe7, 0x68, 0x7f, 0xb3, 0xdb, 0x17,
0x3f, 0x9c, 0xd3, 0x95, 0xcb, 0xbc, 0x06, 0xf9, 0x91, 0x24, 0x2d, 0xb7, 0x86, 0x50, 0x90, 0xa1,
0xbf, 0x2c, 0xbc, 0x3c, 0xf1, 0x72, 0x3f, 0xba, 0x36, 0x3b, 0x04, 0xc2, 0x2e, 0x92, 0x0b, 0x44,
0x1e, 0xb5, 0x8e, 0xad, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0x85, 0xe0, 0xf0, 0x3c, 0xbf, 0x17,
0x00, 0x00,
}

View File

@ -94,11 +94,12 @@ func (c *Client) handleUDPTunnel(buffer []byte) error {
}
// Session
buffer = buffer[1:]
session, n := varint.Decode(buffer)
if n <= 0 {
return errInvalidProtobuf
}
buff := buffer[n:]
buffer = buffer[n:]
user := c.Users[uint32(session)]
if user == nil {
return errInvalidProtobuf
@ -117,25 +118,25 @@ func (c *Client) handleUDPTunnel(buffer []byte) error {
// Sequence
// TODO: use in jitter buffer
_, n = varint.Decode(buff)
_, n = varint.Decode(buffer)
if n <= 0 {
return errInvalidProtobuf
}
buff = buff[n:]
buffer = buffer[n:]
// Length
length, n := varint.Decode(buff)
length, n := varint.Decode(buffer)
if n <= 0 {
return errInvalidProtobuf
}
buff = buff[n:]
buffer = buffer[n:]
// Opus audio packets set the 13th bit in the size field as the terminator.
audioLength := int(length) &^ 0x2000
if audioLength > len(buff) {
if audioLength > len(buffer) {
return errInvalidProtobuf
}
pcm, err := decoder.Decode(buff[:audioLength], AudioMaximumFrameSize)
pcm, err := decoder.Decode(buffer[:audioLength], AudioMaximumFrameSize)
if err != nil {
return err
}
@ -149,13 +150,13 @@ func (c *Client) handleUDPTunnel(buffer []byte) error {
AudioBuffer: AudioBuffer(pcm),
}
if len(buff)-audioLength == 3*4 {
if len(buffer)-audioLength == 3*4 {
// the packet has positional audio data; 3x float32
buff = buff[audioLength:]
buffer = buffer[audioLength:]
event.X = math.Float32frombits(binary.LittleEndian.Uint32(buff))
event.Y = math.Float32frombits(binary.LittleEndian.Uint32(buff[4:]))
event.Z = math.Float32frombits(binary.LittleEndian.Uint32(buff[8:]))
event.X = math.Float32frombits(binary.LittleEndian.Uint32(buffer))
event.Y = math.Float32frombits(binary.LittleEndian.Uint32(buffer[4:]))
event.Z = math.Float32frombits(binary.LittleEndian.Uint32(buffer[8:]))
event.HasPosition = true
}

View File

@ -37,15 +37,13 @@ func Ping(address string, interval, timeout time.Duration) (*PingResponse, error
if timeout < 0 {
return nil, errors.New("gumble: timeout must be positive")
}
addr, err := net.ResolveUDPAddr("udp", address)
if err != nil {
return nil, err
}
conn, err := net.DialUDP("udp", nil, addr)
deadline := time.Now().Add(timeout)
conn, err := net.DialTimeout("udp", address, timeout)
if err != nil {
return nil, err
}
defer conn.Close()
conn.SetReadDeadline(deadline)
var (
idsLock sync.Mutex
@ -83,7 +81,6 @@ func Ping(address string, interval, timeout time.Duration) (*PingResponse, error
buildSendPacket()
conn.SetReadDeadline(time.Now().Add(timeout))
for {
var incoming [24]byte
if _, err := io.ReadFull(conn, incoming[:]); err != nil {
@ -98,7 +95,7 @@ func Ping(address string, interval, timeout time.Duration) (*PingResponse, error
}
return &PingResponse{
Address: addr,
Address: conn.RemoteAddr().(*net.UDPAddr),
Ping: time.Since(sendTime),
Version: Version{
Version: binary.BigEndian.Uint32(incoming[0:]),

View File

@ -36,7 +36,17 @@ func Decode(b []byte) (int64, int) {
if (b[0]&0xFC) == 0xF4 && len(b) >= 9 {
return int64(binary.BigEndian.Uint64(b[1:])), 9
}
// TODO: 111110__ + varint Negative recursive varint
// TODO: 111111xx Byte-inverted negative two bit number (~xx)
// 111110__ + varint Negative recursive varint
if b[0]&0xFC == 0xF8 {
if v, n := Decode(b[1:]); n > 0 {
return -v, n + 1
}
return 0, 0
}
// 111111xx Byte-inverted negative two bit number (~xx)
if b[0]&0xFC == 0xFC {
return ^int64(b[0] & 0x03), 1
}
return 0, 0
}

View File

@ -0,0 +1,32 @@
package varint
import "testing"
func TestRange(t *testing.T) {
fn := func(i int64) {
var b [MaxVarintLen]byte
size := Encode(b[:], i)
if size == 0 {
t.Errorf("Encode returned size 0\n")
}
s := b[:size]
val, size := Decode(s)
if size == 0 {
t.Errorf("Decode return size 0\n")
}
if i != val {
t.Errorf("Encoded %d (%v) equals decoded %d\n", i, s, val)
}
}
for i := int64(-10000); i <= 10000; i++ {
fn(i)
}
fn(134342525)
fn(10282934828342)
fn(1028293482834200000)
}

View File

@ -11,7 +11,11 @@ const MaxVarintLen = 10
// Encode encodes the given value to varint format.
func Encode(b []byte, value int64) int {
// TODO: 111111xx Byte-inverted negative two bit number (~xx)
// 111111xx Byte-inverted negative two bit number (~xx)
if value <= -1 && value >= -4 {
b[0] = 0xFC | byte(^value&0xFF)
return 1
}
// 111110__ + varint Negative recursive varint
if value < 0 {
b[0] = 0xF8

View File

@ -2,3 +2,5 @@
*.sublime-workspace
*.un~
*.swp
.idea/
*.iml

View File

@ -5,7 +5,6 @@
package properties
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
@ -36,14 +35,14 @@ func LoadString(s string) (*Properties, error) {
// LoadFile reads a file into a Properties struct.
func LoadFile(filename string, enc Encoding) (*Properties, error) {
return loadFiles([]string{filename}, enc, false)
return loadAll([]string{filename}, enc, false)
}
// LoadFiles reads multiple files in the given order into
// a Properties struct. If 'ignoreMissing' is true then
// non-existent files will not be reported as error.
func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
return loadFiles(filenames, enc, ignoreMissing)
return loadAll(filenames, enc, ignoreMissing)
}
// LoadURL reads the content of the URL into a Properties struct.
@ -55,7 +54,7 @@ func LoadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Propertie
// encoding is set to UTF-8. A missing content type header is
// interpreted as 'text/plain; charset=utf-8'.
func LoadURL(url string) (*Properties, error) {
return loadURLs([]string{url}, false)
return loadAll([]string{url}, UTF8, false)
}
// LoadURLs reads the content of multiple URLs in the given order into a
@ -63,7 +62,15 @@ func LoadURL(url string) (*Properties, error) {
// not be reported as error. See LoadURL for the Content-Type header
// and the encoding.
func LoadURLs(urls []string, ignoreMissing bool) (*Properties, error) {
return loadURLs(urls, ignoreMissing)
return loadAll(urls, UTF8, ignoreMissing)
}
// LoadAll reads the content of multiple URLs or files in the given order into a
// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
// not be reported as error. Encoding sets the encoding for files. For the URLs please see
// LoadURL for the Content-Type header and the encoding.
func LoadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
return loadAll(names, enc, ignoreMissing)
}
// MustLoadString reads an UTF8 string into a Properties struct and
@ -98,6 +105,14 @@ func MustLoadURLs(urls []string, ignoreMissing bool) *Properties {
return must(LoadURLs(urls, ignoreMissing))
}
// MustLoadAll reads the content of multiple URLs or files in the given order into a
// Properties struct. If 'ignoreMissing' is true then a 404 status code or missing file will
// not be reported as error. Encoding sets the encoding for files. For the URLs please see
// LoadURL for the Content-Type header and the encoding. It panics on error.
func MustLoadAll(names []string, enc Encoding, ignoreMissing bool) *Properties {
return must(LoadAll(names, enc, ignoreMissing))
}
func loadBuf(buf []byte, enc Encoding) (*Properties, error) {
p, err := parse(convert(buf, enc))
if err != nil {
@ -106,66 +121,78 @@ func loadBuf(buf []byte, enc Encoding) (*Properties, error) {
return p, p.check()
}
func loadFiles(filenames []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
var buf bytes.Buffer
for _, filename := range filenames {
f, err := expandFilename(filename)
func loadAll(names []string, enc Encoding, ignoreMissing bool) (*Properties, error) {
result := NewProperties()
for _, name := range names {
n, err := expandName(name)
if err != nil {
return nil, err
}
data, err := ioutil.ReadFile(f)
var p *Properties
if strings.HasPrefix(n, "http://") || strings.HasPrefix(n, "https://") {
p, err = loadURL(n, ignoreMissing)
} else {
p, err = loadFile(n, enc, ignoreMissing)
}
if err != nil {
if ignoreMissing && os.IsNotExist(err) {
LogPrintf("properties: %s not found. skipping", filename)
continue
}
return nil, err
}
result.Merge(p)
// concatenate the buffers and add a new line in case
// the previous file didn't end with a new line
buf.Write(data)
buf.WriteRune('\n')
}
return loadBuf(buf.Bytes(), enc)
return result, result.check()
}
func loadURLs(urls []string, ignoreMissing bool) (*Properties, error) {
var buf bytes.Buffer
for _, u := range urls {
resp, err := http.Get(u)
if err != nil {
return nil, fmt.Errorf("properties: error fetching %q. %s", u, err)
func loadFile(filename string, enc Encoding, ignoreMissing bool) (*Properties, error) {
data, err := ioutil.ReadFile(filename)
if err != nil {
if ignoreMissing && os.IsNotExist(err) {
LogPrintf("properties: %s not found. skipping", filename)
return NewProperties(), nil
}
if resp.StatusCode == 404 && ignoreMissing {
LogPrintf("properties: %s returned %d. skipping", u, resp.StatusCode)
continue
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("properties: %s returned %d", u, resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return nil, fmt.Errorf("properties: %s error reading response. %s", u, err)
}
ct := resp.Header.Get("Content-Type")
var enc Encoding
switch strings.ToLower(ct) {
case "text/plain", "text/plain; charset=iso-8859-1", "text/plain; charset=latin1":
enc = ISO_8859_1
case "", "text/plain; charset=utf-8":
enc = UTF8
default:
return nil, fmt.Errorf("properties: invalid content type %s", ct)
}
buf.WriteString(convert(body, enc))
buf.WriteRune('\n')
return nil, err
}
return loadBuf(buf.Bytes(), UTF8)
p, err := parse(convert(data, enc))
if err != nil {
return nil, err
}
return p, nil
}
func loadURL(url string, ignoreMissing bool) (*Properties, error) {
resp, err := http.Get(url)
if err != nil {
return nil, fmt.Errorf("properties: error fetching %q. %s", url, err)
}
if resp.StatusCode == 404 && ignoreMissing {
LogPrintf("properties: %s returned %d. skipping", url, resp.StatusCode)
return NewProperties(), nil
}
if resp.StatusCode != 200 {
return nil, fmt.Errorf("properties: %s returned %d", url, resp.StatusCode)
}
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return nil, fmt.Errorf("properties: %s error reading response. %s", url, err)
}
ct := resp.Header.Get("Content-Type")
var enc Encoding
switch strings.ToLower(ct) {
case "text/plain", "text/plain; charset=iso-8859-1", "text/plain; charset=latin1":
enc = ISO_8859_1
case "", "text/plain; charset=utf-8":
enc = UTF8
default:
return nil, fmt.Errorf("properties: invalid content type %s", ct)
}
p, err := parse(convert(body, enc))
if err != nil {
return nil, err
}
return p, nil
}
func must(p *Properties, err error) *Properties {
@ -175,12 +202,12 @@ func must(p *Properties, err error) *Properties {
return p
}
// expandFilename expands ${ENV_VAR} expressions in a filename.
// expandName expands ${ENV_VAR} expressions in a name.
// If the environment variable does not exist then it will be replaced
// with an empty string. Malformed expressions like "${ENV_VAR" will
// be reported as error.
func expandFilename(filename string) (string, error) {
return expand(filename, make(map[string]bool), "${", "}", make(map[string]string))
func expandName(name string) (string, error) {
return expand(name, make(map[string]bool), "${", "}", make(map[string]string))
}
// Interprets a byte buffer either as an ISO-8859-1 or UTF-8 encoded string.

View File

@ -124,6 +124,16 @@ func (s *LoadSuite) TestLoadURLFailInvalidEncoding(c *C) {
c.Assert(err, ErrorMatches, ".*invalid content type.*")
}
func (s *LoadSuite) TestLoadAll(c *C) {
filename := s.makeFile(c, "key=value")
filename2 := s.makeFile(c, "key2=value3")
filename3 := s.makeFile(c, "key=value4")
srv := testServer()
defer srv.Close()
p := MustLoadAll([]string{filename, filename2, srv.URL + "/a", srv.URL + "/b", filename3}, UTF8, false)
assertKeyValues(c, "", p, "key", "value4", "key2", "value2")
}
func (s *LoadSuite) SetUpSuite(c *C) {
s.tempFiles = make([]string, 0)
}

View File

@ -630,6 +630,26 @@ func (p *Properties) Delete(key string) {
p.k = newKeys
}
// Merge merges properties, comments and keys from other *Properties into p
func (p *Properties) Merge(other *Properties) {
for k,v := range other.m {
p.m[k] = v
}
for k,v := range other.c {
p.c[k] = v
}
outer:
for _, otherKey := range other.k {
for _, key := range p.k {
if otherKey == key {
continue outer
}
}
p.k = append(p.k, otherKey)
}
}
// ----------------------------------------------------------------------------
// check expands all values and returns an error if a circular reference or

View File

@ -842,6 +842,20 @@ func (s *TestSuite) TestDeleteUnknownKey(c *C) {
c.Check(len(p.k), Equals, 1)
}
func (s *TestSuite) TestMerge(c *C) {
input1 := "#comment\nkey=value\nkey2=value2"
input2 := "#another comment\nkey=another value\nkey3=value3"
p1, err := parse(input1)
c.Assert(err, IsNil)
p2, err := parse(input2)
p1.Merge(p2)
c.Check(len(p1.m), Equals, 3)
c.Check(len(p1.c), Equals, 1)
c.Check(len(p1.k), Equals, 3)
c.Check(p1.MustGet("key"), Equals, "another value")
c.Check(p1.GetComment("key"), Equals, "another comment")
}
// ----------------------------------------------------------------------------
// tests all combinations of delimiters, leading and/or trailing whitespace and newlines.

View File

@ -144,6 +144,7 @@ func getAttrList(path string, attrList attrList, attrBuf []byte, options uint) (
uintptr(options),
0,
)
use(unsafe.Pointer(_p0))
if e1 != 0 {
return nil, e1
}
@ -196,6 +197,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
}
r0, _, e1 := Syscall(SYS_GETFSSTAT64, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1

View File

@ -109,6 +109,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
}
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1

View File

@ -129,6 +129,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
}
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1

View File

@ -111,6 +111,7 @@ func Getfsstat(buf []Statfs_t, flags int) (n int, err error) {
bufsize = unsafe.Sizeof(Statfs_t{}) * uintptr(len(buf))
}
r0, _, e1 := Syscall(SYS_GETFSSTAT, uintptr(_p0), bufsize, uintptr(flags))
use(unsafe.Pointer(_p0))
n = int(r0)
if e1 != 0 {
err = e1