<commit_before>/*
Package signals generates and manipulates signals:- https://en.wikipedia.org/wiki/Signal_processing.

Overview

signals are entirely procedural, all values are calculated as needed, currently no cache.

this package supports only 1-Dimensionsal variation, and for simplicity the terminolology used represents analogue variation in time.

this package is intended to be general, and so a base package for import, and then used with specific real-world quantities.

Fundamental Types

Level :- can have a value from -MaxLevel to +MaxLevel
Interval :- 'usually' can be used as if infinite (+ve and -ve), with UnitTime somewhere near the center of its precision range.

Interfaces

Signal :- has method Level() which returns a Level value from an Interval value parameter.
Tone :- a Signal with an additional method  Period(), that returns the signals repeat period Interval.

*/
package signals

<commit_msg>formatting<commit_after>/*
Package signals generates and manipulates signals:- https://en.wikipedia.org/wiki/Signal_processing.

Overview

signals are entirely procedural, all values are calculated as needed, currently no cache.

this package supports only 1-Dimensionsal variation, and for simplicity the terminolology used represents analogue variation in time.

this package is intended to be general, and so a base package for import, and then used with specific real-world quantities.

Fundamental Types

Level :- can have a value from -MaxLevel to +MaxLevel

Interval :- 'usually' can be used as if infinite (+ve and -ve), with UnitTime somewhere near the center of its precision range.

Interfaces

Signal :- has method Level() which returns a Level value from an Interval value parameter.

Tone :- a Signal with an additional method  Period(), that returns the signals assumed repeat period Interval.

*/
package signals

<|endoftext|>


<commit_before>/*
Package goserver provide request router with middleware

## Basic example

	package main

	import (
		"fmt"
		"log"
		"net/http"

		"github.com/vardius/goserver"
	)

	func Index(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Welcome!\n")
	}

	func Hello(w http.ResponseWriter, r *http.Request) {
		params, _ := goserver.ParamsFromContext(r.Context())
		fmt.Fprintf(w, "hello, %s!\n", params.Value("name"))
	}

	func main() {
		server := goserver.New()
		server.GET("/", Index)
		server.GET("/hello/:name", Hello)

		log.Fatal(http.ListenAndServe(":8080", server))
	}

## Routing

The router determines how to handle that request.
Goserver uses a routing tree. Once one branch of the tree matches, only routes inside that branch are considered,
not any routes after that branch. When instantiating server, the root node of router tree is created.

### Route types

	- Static `/hello`
	will match requests matching given route
	- Named `/:name`
	will match requests matching given route scheme
	- Regexp `/:name:[a-z]+`
	will match requests matching given route scheme and its regexp

#### Wildcards

The values of *named parameter* or *regexp parameters* are accessible via *request context*
`params, ok := goserver.ParamsFromContext(req.Context())`.
You can get the value of a parameter either by its index in the slice, or by using the `params.Value(name)` method:
`:name` or `/:name:[a-z]+` can be retrived by `params.Value("name")`.

### Defining Routes

A full route definition contain up to three parts:

	1. HTTP method under which route will be available
	2. The URL path route. This is matched against the URL passed to the server,
	and can contain named wildcard placeholders *(e.g. :placeholders)* to match dynamic parts in the URL.
	3. `http.HandleFunc`, which tells the server to handle matched requests to the router with handler.

Take the following example:

	server.GET("/hello/:name:r([a-z]+)go", func(w http.ResponseWriter, r *http.Request) {
		params, _ := goserver.ParamsFromContext(r.Context())
		fmt.Fprintf(w, "hello, %s!\n", params.Value("name"))
	})

In this case, the route is matched by `/hello/rxxxxxgo` for example,
because the `:name` wildcard matches the regular expression wildcard given (`r([a-z]+)go`). However,
`/hello/foo` does not match, because "foo" fails the *name* wildcard. When using wildcards,
these are returned in the map from request context. The part of the path that the wildcard matched (e.g. *rxxxxxgo*) is used as value.
*/
package goserver
<commit_msg>Removed markdown from docs<commit_after>/*
Package goserver provide request router with middleware

Basic example

	package main

	import (
		"fmt"
		"log"
		"net/http"

		"github.com/vardius/goserver"
	)

	func Index(w http.ResponseWriter, r *http.Request) {
		fmt.Fprint(w, "Welcome!\n")
	}

	func Hello(w http.ResponseWriter, r *http.Request) {
		params, _ := goserver.ParamsFromContext(r.Context())
		fmt.Fprintf(w, "hello, %s!\n", params.Value("name"))
	}

	func main() {
		server := goserver.New()
		server.GET("/", Index)
		server.GET("/hello/:name", Hello)

		log.Fatal(http.ListenAndServe(":8080", server))
	}

Routing
The router determines how to handle that request.
Goserver uses a routing tree. Once one branch of the tree matches, only routes inside that branch are considered,
not any routes after that branch. When instantiating server, the root node of router tree is created.

Route types
- Static `/hello`
will match requests matching given route
- Named `/:name`
will match requests matching given route scheme
- Regexp `/:name:[a-z]+`
will match requests matching given route scheme and its regexp

Wildcards
The values of *named parameter* or *regexp parameters* are accessible via *request context*
`params, ok := goserver.ParamsFromContext(req.Context())`.
You can get the value of a parameter either by its index in the slice, or by using the `params.Value(name)` method:
`:name` or `/:name:[a-z]+` can be retrived by `params.Value("name")`.

Defining Routes
A full route definition contain up to three parts:
1. HTTP method under which route will be available
2. The URL path route. This is matched against the URL passed to the server,
and can contain named wildcard placeholders *(e.g. :placeholders)* to match dynamic parts in the URL.
3. `http.HandleFunc`, which tells the server to handle matched requests to the router with handler.

Take the following example:

	server.GET("/hello/:name:r([a-z]+)go", func(w http.ResponseWriter, r *http.Request) {
		params, _ := goserver.ParamsFromContext(r.Context())
		fmt.Fprintf(w, "hello, %s!\n", params.Value("name"))
	})

In this case, the route is matched by `/hello/rxxxxxgo` for example,
because the `:name` wildcard matches the regular expression wildcard given (`r([a-z]+)go`). However,
`/hello/foo` does not match, because "foo" fails the *name* wildcard. When using wildcards,
these are returned in the map from request context. The part of the path that the wildcard matched (e.g. *rxxxxxgo*) is used as value.
*/
package goserver
<|endoftext|>


<commit_before>/*
Package petrel provides a TCP or Unix domain socket with builtin
request dispatch.

Petrel is not an HTTP service. It directly manages sockets, so it is
self-contained and compact. It is intended to be unobtrusive and easy
to integrate into applications.

BASIC USAGE

Instantiate a handler:

HOW IT WORKS

HANDLER.MSGR AND MSGS

Msgr is a buffered channel, capable of holding 32 Msgs. If the buffer
fills up, new messages are dropped on the floor to avoid blocking.

The exception to this is a message with a code of 599. It is allowed
to block, since it indicates that the listener socket has stopped
working. If a 599 is received, immediately halt the petrel instance.

Msg.Status tells you what has happened.

Which messages are sent to Msgr is determined by petrel.Config.Msglvl.

    * Fatal is fatal errors only (599)
    * Error adds all other Petrel errors (all 500s)
    * Conn adds messages about connection opens/closes
    * All adds everything else

Messages which are not errors according Petrel may have a Msg.Err
value other than nil. Client disconnects for instance, pass along the
socket read error which triggered them.

SHUTDOWN AND CLEANUP

When Server.Quit() is called, the instance stops accepting new
connections, and waits for all existing connections to terminate.

If the Server was configured with long timeouts (or no timeout at
all), then Quit() may block for a long time.

Once Quit() returns, the Server is fully shut down. If you are
recovering from a listener socket error (code 599), it is safe to
spawn a new Server at this point.
*/
package petrel
<commit_msg>doc wip<commit_after>/*
Package petrel provides a simple-to-use networking server and client,
with builtin request dispatch. It is intended to be unobtrusive and
easy to integrate into applications.

QUICK START

Instantiate a handler:

HOW IT WORKS

HANDLER.MSGR AND MSGS

Msgr is a buffered channel, capable of holding 32 Msgs. If the buffer
fills up, new messages are dropped on the floor to avoid blocking.

The exception to this is a message with a code of 599. It is allowed
to block, since it indicates that the listener socket has stopped
working. If a 599 is received, immediately halt the petrel instance.

Msg.Status tells you what has happened.

Which messages are sent to Msgr is determined by petrel.Config.Msglvl.

    * Fatal is fatal errors only (599)
    * Error adds all other Petrel errors (all 500s)
    * Conn adds messages about connection opens/closes
    * All adds everything else

Messages which are not errors according Petrel may have a Msg.Err
value other than nil. Client disconnects for instance, pass along the
socket read error which triggered them.

SHUTDOWN AND CLEANUP

When Server.Quit() is called, the instance stops accepting new
connections, and waits for all existing connections to terminate.

If the Server was configured with long timeouts (or no timeout at
all), then Quit() may block for a long time.

Once Quit() returns, the Server is fully shut down. If you are
recovering from a listener socket error (code 599), it is safe to
spawn a new Server at this point.
*/
package petrel
<|endoftext|>


<commit_before>// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package ebiten provides graphics and input API to develop a 2D game.
//
// You can start the game by calling the function Run.
//
//     // update is called every frame (1/60 [s]).
//     func update(screen *ebiten.Image) error {
//
//         // Write your game's logical update.
//
//         if IsRunningSlowly() {
//             // When the game is running slowly, the rendering result
//             // will not be adopted.
//             return nil
//         }
//
//         // Write your game's rendering.
//
//         return nil
//     }
//
//     func main() {
//         // Call ebiten.Run to start your game loop.
//         ebiten.Run(update, 320, 240, 2, "Your game's title")
//     }
package ebiten
<commit_msg>doc: Add explanation about EBITEN_SCREENSHOT_KEY<commit_after>// Copyright 2014 Hajime Hoshi
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package ebiten provides graphics and input API to develop a 2D game.
//
// You can start the game by calling the function Run.
//
//     // update is called every frame (1/60 [s]).
//     func update(screen *ebiten.Image) error {
//
//         // Write your game's logical update.
//
//         if IsRunningSlowly() {
//             // When the game is running slowly, the rendering result
//             // will not be adopted.
//             return nil
//         }
//
//         // Write your game's rendering.
//
//         return nil
//     }
//
//     func main() {
//         // Call ebiten.Run to start your game loop.
//         ebiten.Run(update, 320, 240, 2, "Your game's title")
//     }
//
// The EBITEN_SCREENSHOT_KEY environment variable specified the key
// to take a screenshot. For example, if you run your game with
// `EBITEN_SCREENSHOT_KEY=q`, you can take a game screen's screenshot
// by pressing Q key. The image file is saved at the current directory
// with the name screen*.png.
package ebiten
<|endoftext|>


<commit_before>/*
Package telnet provides TELNET and TELNETS client and server implementations
in a style similar to the "net/http" library that is part of the Go standard library,
including support for "middleware"; TELNETS is secure TELNET, with the TELNET protocol
over a secured TLS (or SSL) connection.

Example TELNET Server

ListenAndServe starts a TELNET server with a given address and handler.

	handler := telnet.EchoHandler

	err := telnet.ListenAndServe(":23", handler)
	if nil != err {
		panic(err)
	}

Example TELNETS Server

ListenAndServeTLS starts a (secure) TELNETS server with a given address and handler,
using the specified "cert.pem" and "key.pem" files.

	handler := telnet.EchoHandler

	err := telnet.ListenAndServeTLS(":992", "cert.pem", "key.pem", handler)
	if nil != err {
		panic(err)
	}

TELNET vs TELNETS

If you are communicating over the open Internet, you should be using (the secure) TELNETS and ListenAndServeTLS.

If you are communicating just on localhost, then using just (the un-secure) TELNET and telnet.ListenAndServe may be OK.

If you are not sure which to use, use TELNETS and ListenAndServeTLS.

Example TELNET Shell Server

The previous 2 exaple servers were very very simple. Specifically, they just echoed back whatever
you submitted to it.

If you typed:

	Apple Banana Cherry\r\n

... it would send back:

	Apple Banana Cherry\r\n

(Exactly the same data you sent it.)

A more useful TELNET server can be made using the "github.com/reiver/go-telnet/telsh" sub-package.

The `telsh` sub-package provides "middleware" that enables you to create a "shell" interface (also
called a "command line interface" or "CLI") which most people would expect when using TELNET OR TELNETS.

For example:

	package main

	import (
		"github.com/reiver/go-oi"
		"github.com/reiver/go-telnet"
		"github.com/reiver/go-telnet/telsh"

		"time"
	)

	func main() {

		shellHandler := telsh.NewShellHandler()

		commandName := "date"
		shellHandler.Register(commandName, danceProducer)

		commandName = "animate"
		shellHandler.Register(commandName, animateProducer)

		addr := ":23"
		if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
			panic(err)
		}
	}

Note that in the example, so far, we have registered 2 commands: `date` and `animate`.

For this to actually work, we need to have code for the `date` and `animate` commands.

The actual implemenation for the `date` command could be done like the following:

	func dateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
		const layout = "Mon Jan 2 15:04:05 -0700 MST 2006"
		s := time.Now().Format(layout)

		if _, err := oi.LongWriteString(stdout, s); nil != err {
			return err
		}

		return nil
	}

	func dateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(dateHandler)
	}

	var dateProducer = ProducerFunc(dateProducerFunc)

Note that your "real" work is in the `dateHandlerFunc` func.

And the actual implementation for the `animate` command could as done as follows:

	func animateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {

		for i:=0; i<20; i++ {
			oi.LongWriteString(stdout, "\r⠋")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠙")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠹")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠸")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠼")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠴")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠦")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠧")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠇")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠏")
			time.Sleep(50*time.Millisecond)
		}
		oi.LongWriteString(stdout, "\r \r\n")

		return nil
	}

	func animateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(animateHandler)
	}

	var animateProducer = ProducerFunc(animateProducerFunc)

Again, note that your "real" work is in the `animateHandlerFunc` func.

Generating PEM Files

If you are using the telnet.ListenAndServeTLS func or the telnet.Server.ListenAndServeTLS method, you will need to
supply "cert.pem" and "key.pem" files.

If you do not already have these files, the Go soure code contains a tool for generating these files for you.

It can be found at:

	$GOROOT/src/crypto/tls/generate_cert.go

So, for example, if your `$GOROOT` is the "/usr/local/go" directory, then it would be at:

	/usr/local/go/src/crypto/tls/generate_cert.go

If you run the command:

	go run $GOROOT/src/crypto/tls/generate_cert.go --help

... then you get the help information for "generate_cert.go".

Of course, you would replace or set `$GOROOT` with whatever your path actualy is. Again, for example,
if your `$GOROOT` is the "/usr/local/go" directory, then it would be:

	go run /usr/local/go/src/crypto/tls/generate_cert.go --help

To demonstrate the usage of "generate_cert.go", you might run the following to generate certificates
that were bound to the hosts `127.0.0.1` and `localhost`:

	go run /usr/local/go/src/crypto/tls/generate_cert.go --ca --host='127.0.0.1,localhost'

If you are not sure where "generate_cert.go" is on your computer, on Linux and Unix based systems, you might
be able to find the file with the command:

	locate /src/crypto/tls/generate_cert.go

(If it finds it, it should output the full path to this file.)

Terminal Codes

Terminal codes (also sometimes called 'terminal control codes') are used to issue various kinds of commands
to the terminal.

(Note that 'terminal control codes' are a completely separate concept for 'TELNET commands',
and the two should NOT be conflated or confused.)

The most common types of 'terminal codes' are the 'ANSI escape codes'. (Although there are other types too.)

ANSI Escape Codes

ANSI escape codes (also sometimes called 'ANSI escape sequences') are a common type of 'terminal code' used
to do things such as:

• moving the cursor,

• erasing the display,

• erasing the line,

• setting the graphics mode,

• setting the foregroup color,

• setting the background color,

• setting the screen resolution, and

• setting keyboard strings.

Setting The Foreground Color With ANSI Escape Codes

One of the abilities of ANSI escape codes is to set the foreground color.

Here is a table showing codes for this:

	| ANSI Color   | Go string    | Go []byte                       |
	| ------------ | ------------ | ------------------------------- |
	| Black        | `"\x1b[30m"` | `[]byte{27, '[', '3','0', 'm'}` |
	| Red          | `"\x1b[31m"` | `[]byte{27, '[', '3','1', 'm'}` |
	| Green        | `"\x1b[32m"` | `[]byte{27, '[', '3','2', 'm'}` |
	| Brown/Yellow | `"\x1b[33m"` | `[]byte{27, '[', '3','3', 'm'}` |
	| Blue         | `"\x1b[34m"` | `[]byte{27, '[', '3','4', 'm'}` |
	| Magenta      | `"\x1b[35m"` | `[]byte{27, '[', '3','5', 'm'}` |
	| Cyan         | `"\x1b[36m"` | `[]byte{27, '[', '3','6', 'm'}` |
	| Gray/White   | `"\x1b[37m"` | `[]byte{27, '[', '3','7', 'm'}` |

(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'3'` and whatever.)

Setting The Background Color With ANSI Escape Codes

Another of the abilities of ANSI escape codes is to set the background color.

	| ANSI Color   | Go string    | Go []byte                       |
	| ------------ | ------------ | ------------------------------- |
	| Black        | `"\x1b[40m"` | `[]byte{27, '[', '4','0', 'm'}` |
	| Red          | `"\x1b[41m"` | `[]byte{27, '[', '4','1', 'm'}` |
	| Green        | `"\x1b[42m"` | `[]byte{27, '[', '4','2', 'm'}` |
	| Brown/Yellow | `"\x1b[43m"` | `[]byte{27, '[', '4','3', 'm'}` |
	| Blue         | `"\x1b[44m"` | `[]byte{27, '[', '4','4', 'm'}` |
	| Magenta      | `"\x1b[45m"` | `[]byte{27, '[', '4','5', 'm'}` |
	| Cyan         | `"\x1b[46m"` | `[]byte{27, '[', '4','6', 'm'}` |
	| Gray/White   | `"\x1b[47m"` | `[]byte{27, '[', '4','7', 'm'}` |

(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'3'` and whatever.)

*/
package telnet
<commit_msg>updated docs<commit_after>/*
Package telnet provides TELNET and TELNETS client and server implementations
in a style similar to the "net/http" library that is part of the Go standard library,
including support for "middleware"; TELNETS is secure TELNET, with the TELNET protocol
over a secured TLS (or SSL) connection.

Example TELNET Server

ListenAndServe starts a TELNET server with a given address and handler.

	handler := telnet.EchoHandler

	err := telnet.ListenAndServe(":23", handler)
	if nil != err {
		panic(err)
	}

Example TELNETS Server

ListenAndServeTLS starts a (secure) TELNETS server with a given address and handler,
using the specified "cert.pem" and "key.pem" files.

	handler := telnet.EchoHandler

	err := telnet.ListenAndServeTLS(":992", "cert.pem", "key.pem", handler)
	if nil != err {
		panic(err)
	}

TELNET vs TELNETS

If you are communicating over the open Internet, you should be using (the secure) TELNETS and ListenAndServeTLS.

If you are communicating just on localhost, then using just (the un-secure) TELNET and telnet.ListenAndServe may be OK.

If you are not sure which to use, use TELNETS and ListenAndServeTLS.

Example TELNET Shell Server

The previous 2 exaple servers were very very simple. Specifically, they just echoed back whatever
you submitted to it.

If you typed:

	Apple Banana Cherry\r\n

... it would send back:

	Apple Banana Cherry\r\n

(Exactly the same data you sent it.)

A more useful TELNET server can be made using the "github.com/reiver/go-telnet/telsh" sub-package.

The `telsh` sub-package provides "middleware" that enables you to create a "shell" interface (also
called a "command line interface" or "CLI") which most people would expect when using TELNET OR TELNETS.

For example:

	package main

	import (
		"github.com/reiver/go-oi"
		"github.com/reiver/go-telnet"
		"github.com/reiver/go-telnet/telsh"

		"time"
	)

	func main() {

		shellHandler := telsh.NewShellHandler()

		commandName := "date"
		shellHandler.Register(commandName, danceProducer)

		commandName = "animate"
		shellHandler.Register(commandName, animateProducer)

		addr := ":23"
		if err := telnet.ListenAndServe(addr, shellHandler); nil != err {
			panic(err)
		}
	}

Note that in the example, so far, we have registered 2 commands: `date` and `animate`.

For this to actually work, we need to have code for the `date` and `animate` commands.

The actual implemenation for the `date` command could be done like the following:

	func dateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {
		const layout = "Mon Jan 2 15:04:05 -0700 MST 2006"
		s := time.Now().Format(layout)

		if _, err := oi.LongWriteString(stdout, s); nil != err {
			return err
		}

		return nil
	}

	func dateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(dateHandler)
	}

	var dateProducer = ProducerFunc(dateProducerFunc)

Note that your "real" work is in the `dateHandlerFunc` func.

And the actual implementation for the `animate` command could as done as follows:

	func animateHandlerFunc(stdin io.ReadCloser, stdout io.WriteCloser, stderr io.WriteCloser) error {

		for i:=0; i<20; i++ {
			oi.LongWriteString(stdout, "\r⠋")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠙")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠹")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠸")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠼")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠴")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠦")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠧")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠇")
			time.Sleep(50*time.Millisecond)

			oi.LongWriteString(stdout, "\r⠏")
			time.Sleep(50*time.Millisecond)
		}
		oi.LongWriteString(stdout, "\r \r\n")

		return nil
	}

	func animateProducerFunc(ctx telsh.Context, name string, args ...string) telsh.Handler{
		return telsh.PromoteHandlerFunc(animateHandler)
	}

	var animateProducer = ProducerFunc(animateProducerFunc)

Again, note that your "real" work is in the `animateHandlerFunc` func.

Generating PEM Files

If you are using the telnet.ListenAndServeTLS func or the telnet.Server.ListenAndServeTLS method, you will need to
supply "cert.pem" and "key.pem" files.

If you do not already have these files, the Go soure code contains a tool for generating these files for you.

It can be found at:

	$GOROOT/src/crypto/tls/generate_cert.go

So, for example, if your `$GOROOT` is the "/usr/local/go" directory, then it would be at:

	/usr/local/go/src/crypto/tls/generate_cert.go

If you run the command:

	go run $GOROOT/src/crypto/tls/generate_cert.go --help

... then you get the help information for "generate_cert.go".

Of course, you would replace or set `$GOROOT` with whatever your path actualy is. Again, for example,
if your `$GOROOT` is the "/usr/local/go" directory, then it would be:

	go run /usr/local/go/src/crypto/tls/generate_cert.go --help

To demonstrate the usage of "generate_cert.go", you might run the following to generate certificates
that were bound to the hosts `127.0.0.1` and `localhost`:

	go run /usr/local/go/src/crypto/tls/generate_cert.go --ca --host='127.0.0.1,localhost'

If you are not sure where "generate_cert.go" is on your computer, on Linux and Unix based systems, you might
be able to find the file with the command:

	locate /src/crypto/tls/generate_cert.go

(If it finds it, it should output the full path to this file.)

Terminal Codes

Terminal codes (also sometimes called 'terminal control codes') are used to issue various kinds of commands
to the terminal.

(Note that 'terminal control codes' are a completely separate concept for 'TELNET commands',
and the two should NOT be conflated or confused.)

The most common types of 'terminal codes' are the 'ANSI escape codes'. (Although there are other types too.)

ANSI Escape Codes

ANSI escape codes (also sometimes called 'ANSI escape sequences') are a common type of 'terminal code' used
to do things such as:

• moving the cursor,

• erasing the display,

• erasing the line,

• setting the graphics mode,

• setting the foregroup color,

• setting the background color,

• setting the screen resolution, and

• setting keyboard strings.

Setting The Foreground Color With ANSI Escape Codes

One of the abilities of ANSI escape codes is to set the foreground color.

Here is a table showing codes for this:

	| ANSI Color   | Go string    | Go []byte                       |
	| ------------ | ------------ | ------------------------------- |
	| Black        | `"\x1b[30m"` | `[]byte{27, '[', '3','0', 'm'}` |
	| Red          | `"\x1b[31m"` | `[]byte{27, '[', '3','1', 'm'}` |
	| Green        | `"\x1b[32m"` | `[]byte{27, '[', '3','2', 'm'}` |
	| Brown/Yellow | `"\x1b[33m"` | `[]byte{27, '[', '3','3', 'm'}` |
	| Blue         | `"\x1b[34m"` | `[]byte{27, '[', '3','4', 'm'}` |
	| Magenta      | `"\x1b[35m"` | `[]byte{27, '[', '3','5', 'm'}` |
	| Cyan         | `"\x1b[36m"` | `[]byte{27, '[', '3','6', 'm'}` |
	| Gray/White   | `"\x1b[37m"` | `[]byte{27, '[', '3','7', 'm'}` |

(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'3'` and whatever.)

Setting The Background Color With ANSI Escape Codes

Another of the abilities of ANSI escape codes is to set the background color.

	| ANSI Color   | Go string    | Go []byte                       |
	| ------------ | ------------ | ------------------------------- |
	| Black        | `"\x1b[40m"` | `[]byte{27, '[', '4','0', 'm'}` |
	| Red          | `"\x1b[41m"` | `[]byte{27, '[', '4','1', 'm'}` |
	| Green        | `"\x1b[42m"` | `[]byte{27, '[', '4','2', 'm'}` |
	| Brown/Yellow | `"\x1b[43m"` | `[]byte{27, '[', '4','3', 'm'}` |
	| Blue         | `"\x1b[44m"` | `[]byte{27, '[', '4','4', 'm'}` |
	| Magenta      | `"\x1b[45m"` | `[]byte{27, '[', '4','5', 'm'}` |
	| Cyan         | `"\x1b[46m"` | `[]byte{27, '[', '4','6', 'm'}` |
	| Gray/White   | `"\x1b[47m"` | `[]byte{27, '[', '4','7', 'm'}` |

(Note that in the `[]byte` that the first `byte` is the number `27` (which
is the "escape" character) where the third and fouth characters are the
**not** number literals, but instead character literals `'4'` and whatever.)

*/
package telnet
<|endoftext|>


<commit_before>/*
Package dendrite implements a distributed hash table (DTH) based on Chord Protocol.
Included sub-package 'dtable' is built on top of dendrite and implements
distributed in-memory key/value database, with replication and failover support,
with query interface to Get() or Set() items with different consistency levels.

For better key distribution, dendrite allows configurable number of virtual nodes
per instance (vnodes).
*/
package dendrite
<commit_msg>updates documentation<commit_after>/*
Package dendrite implements a distributed hash table (DTH) based on Chord Protocol.
Included sub-package 'dtable' is built on top of dendrite and implements
distributed in-memory key/value database, with replication and failover support,
with query interface to Get() or Set() items with different consistency levels.

For better key distribution, dendrite allows configurable number of virtual nodes
per instance (vnodes). The number of replicas in dtable is also configurable.

Calling application can bootstrap the cluster, or join existing one by connecting to any of
existing nodes (must be manually specified). Node discovery is not part of the implementation.
Use consul (consul.io) or something else for that purpose.

Node to node (network) communication is built on top of TCP over ZeroMQ sockets for speed, clustering
and reliability. Dendrite starts configurable number of goroutines (default: 10) for serving remote requests,
but scales that number up and down depending on the load (aka prefork model).

All messages sent through dendrite are encapsulated in ChordMsg structure, where first byte indicates message type,
and actual data follows. Data part is serialized with protocol buffers.

Dendrite can be extended through two interfaces:
-	TransportHook
-	DelegateHook

TransportHook allows other packages to provide additional message types, decoders and handlers, while DelegateHook
can be used to capture chord events that dendrite emits:
- EvPredecessorJoined
- EvPredecessorLeft
- EvReplicasChanged
*/
package dendrite
<|endoftext|>


<commit_before>// Package pgx is a PostgreSQL database driver.
/*
pgx provides lower level access to PostgreSQL than the standard database/sql.
It remains as similar to the database/sql interface as possible while
providing better speed and access to PostgreSQL specific features. Import
github.com/jackc/pgx/stdlib to use pgx as a database/sql compatible driver.

Query Interface

pgx implements Query and Scan in the familiar database/sql style.

    var sum int32

    // Send the query to the server. The returned rows MUST be closed
    // before conn can be used again.
    rows, err := conn.Query("select generate_series(1,$1)", 10)
    if err != nil {
        return err
    }

    // rows.Close is called by rows.Next when all rows are read
    // or an error occurs in Next or Scan. So it may optionally be
    // omitted if nothing in the rows.Next loop can panic. It is
    // safe to close rows multiple times.
    defer rows.Close()

    // Iterate through the result set
    for rows.Next() {
        var n int32
        err = rows.Scan(&n)
        if err != nil {
            return err
        }
        sum += n
    }

    // Any errors encountered by rows.Next or rows.Scan will be returned here
    if rows.Err() != nil {
        return err
    }

    // No errors found - do something with sum

pgx also implements QueryRow in the same style as database/sql.

    var name string
    var weight int64
    err := conn.QueryRow("select name, weight from widgets where id=$1", 42).Scan(&name, &weight)
    if err != nil {
        return err
    }

Use Exec to execute a query that does not return a result set.

    commandTag, err := conn.Exec("delete from widgets where id=$1", 42)
    if err != nil {
        return err
    }
    if commandTag.RowsAffected() != 1 {
        return errors.New("No row found to delete")
    }

Connection Pool

Connection pool usage is explicit and configurable. In pgx, a connection can be
created and managed directly, or a connection pool with a configurable maximum
connections can be used. The connection pool offers an after connect hook that
allows every connection to be automatically setup before being made available in
the connection pool.

It delegates methods such as QueryRow to an automatically checked out and
released connection so you can avoid manually acquiring and releasing
connections when you do not need that level of control.

    var name string
    var weight int64
    err := pool.QueryRow("select name, weight from widgets where id=$1", 42).Scan(&name, &weight)
    if err != nil {
        return err
    }

Base Type Mapping

pgx maps between all common base types directly between Go and PostgreSQL. In
particular:

    Go           PostgreSQL
    -----------------------
    string       varchar
                 text

    // Integers are automatically be converted to any other integer type if
    // it can be done without overflow or underflow.
    int8
    int16        smallint
    int32        int
    int64        bigint
    int
    uint8
    uint16
    uint32
    uint64
    uint

    // Floats are strict and do not automatically convert like integers.
    float32      float4
    float64      float8

    time.Time   date
                timestamp
                timestamptz

    []byte      bytea

Null Mapping

pgx can map nulls in two ways. The first is package pgtype provides types that
have a data field and a status field. They work in a similar fashion to
database/sql. The second is to use a pointer to a pointer.

    var foo pgtype.Varchar
    var bar *string
    err := conn.QueryRow("select foo, bar from widgets where id=$1", 42).Scan(&a, &b)
    if err != nil {
        return err
    }

Array Mapping

pgx maps between int16, int32, int64, float32, float64, and string Go slices
and the equivalent PostgreSQL array type. Go slices of native types do not
support nulls, so if a PostgreSQL array that contains a null is read into a
native Go slice an error will occur. The pgtype package includes many more
array types for PostgreSQL types that do not directly map to native Go types.

JSON and JSONB Mapping

pgx includes built-in support to marshal and unmarshal between Go types and
the PostgreSQL JSON and JSONB.

Inet and CIDR Mapping

pgx encodes from net.IPNet to and from inet and cidr PostgreSQL types. In
addition, as a convenience pgx will encode from a net.IP; it will assume a /32
netmask for IPv4 and a /128 for IPv6.

Custom Type Support

pgx includes support for the common data types like integers, floats, strings,
dates, and times that have direct mappings between Go and SQL. In addition,
pgx uses the github.com/jackc/pgx/pgtype library to support more types. See
documention for that library for instructions on how to implement custom
types.

See example_custom_type_test.go for an example of a custom type for the
PostgreSQL point type.

pgx also includes support for custom types implementing the database/sql.Scanner
and database/sql/driver.Valuer interfaces.

If pgx does cannot natively encode a type and that type is a renamed type (e.g.
type MyTime time.Time) pgx will attempt to encode the underlying type. While
this is usually desired behavior it can produce suprising behavior if one the
underlying type and the renamed type each implement database/sql interfaces and
the other implements pgx interfaces. It is recommended that this situation be
avoided by implementing pgx interfaces on the renamed type.

Raw Bytes Mapping

[]byte passed as arguments to Query, QueryRow, and Exec are passed unmodified
to PostgreSQL.

Transactions

Transactions are started by calling Begin or BeginEx. The BeginEx variant
can create a transaction with a specified isolation level.

    tx, err := conn.Begin()
    if err != nil {
        return err
    }
    // Rollback is safe to call even if the tx is already closed, so if
    // the tx commits successfully, this is a no-op
    defer tx.Rollback()

    _, err = tx.Exec("insert into foo(id) values (1)")
    if err != nil {
        return err
    }

    err = tx.Commit()
    if err != nil {
        return err
    }

Copy Protocol

Use CopyFrom to efficiently insert multiple rows at a time using the PostgreSQL
copy protocol. CopyFrom accepts a CopyFromSource interface. If the data is already
in a [][]interface{} use CopyFromRows to wrap it in a CopyFromSource interface. Or
implement CopyFromSource to avoid buffering the entire data set in memory.

    rows := [][]interface{}{
        {"John", "Smith", int32(36)},
        {"Jane", "Doe", int32(29)},
    }

    copyCount, err := conn.CopyFrom(
        pgx.Identifier{"people"},
        []string{"first_name", "last_name", "age"},
        pgx.CopyFromRows(rows),
    )

CopyFrom can be faster than an insert with as few as 5 rows.

Listen and Notify

pgx can listen to the PostgreSQL notification system with the
WaitForNotification function. It takes a maximum time to wait for a
notification.

    err := conn.Listen("channelname")
    if err != nil {
        return nil
    }

    if notification, err := conn.WaitForNotification(time.Second); err != nil {
        // do something with notification
    }

TLS

The pgx ConnConfig struct has a TLSConfig field. If this field is
nil, then TLS will be disabled. If it is present, then it will be used to
configure the TLS connection. This allows total configuration of the TLS
connection.

Logging

pgx defines a simple logger interface. Connections optionally accept a logger
that satisfies this interface. Set LogLevel to control logging verbosity.
Adapters for github.com/inconshreveable/log15, github.com/sirupsen/logrus, and
the testing log are provided in the log directory.
*/
package pgx
<commit_msg>Update doc.go<commit_after>// Package pgx is a PostgreSQL database driver.
/*
pgx provides lower level access to PostgreSQL than the standard database/sql.
It remains as similar to the database/sql interface as possible while
providing better speed and access to PostgreSQL specific features. Import
github.com/jackc/pgx/stdlib to use pgx as a database/sql compatible driver.

Query Interface

pgx implements Query and Scan in the familiar database/sql style.

    var sum int32

    // Send the query to the server. The returned rows MUST be closed
    // before conn can be used again.
    rows, err := conn.Query("select generate_series(1,$1)", 10)
    if err != nil {
        return err
    }

    // rows.Close is called by rows.Next when all rows are read
    // or an error occurs in Next or Scan. So it may optionally be
    // omitted if nothing in the rows.Next loop can panic. It is
    // safe to close rows multiple times.
    defer rows.Close()

    // Iterate through the result set
    for rows.Next() {
        var n int32
        err = rows.Scan(&n)
        if err != nil {
            return err
        }
        sum += n
    }

    // Any errors encountered by rows.Next or rows.Scan will be returned here
    if rows.Err() != nil {
        return err
    }

    // No errors found - do something with sum

pgx also implements QueryRow in the same style as database/sql.

    var name string
    var weight int64
    err := conn.QueryRow("select name, weight from widgets where id=$1", 42).Scan(&name, &weight)
    if err != nil {
        return err
    }

Use Exec to execute a query that does not return a result set.

    commandTag, err := conn.Exec("delete from widgets where id=$1", 42)
    if err != nil {
        return err
    }
    if commandTag.RowsAffected() != 1 {
        return errors.New("No row found to delete")
    }

Connection Pool

Connection pool usage is explicit and configurable. In pgx, a connection can be
created and managed directly, or a connection pool with a configurable maximum
connections can be used. The connection pool offers an after connect hook that
allows every connection to be automatically setup before being made available in
the connection pool.

It delegates methods such as QueryRow to an automatically checked out and
released connection so you can avoid manually acquiring and releasing
connections when you do not need that level of control.

    var name string
    var weight int64
    err := pool.QueryRow("select name, weight from widgets where id=$1", 42).Scan(&name, &weight)
    if err != nil {
        return err
    }

Base Type Mapping

pgx maps between all common base types directly between Go and PostgreSQL. In
particular:

    Go           PostgreSQL
    -----------------------
    string       varchar
                 text

    // Integers are automatically be converted to any other integer type if
    // it can be done without overflow or underflow.
    int8
    int16        smallint
    int32        int
    int64        bigint
    int
    uint8
    uint16
    uint32
    uint64
    uint

    // Floats are strict and do not automatically convert like integers.
    float32      float4
    float64      float8

    time.Time   date
                timestamp
                timestamptz

    []byte      bytea

Null Mapping

pgx can map nulls in two ways. The first is package pgtype provides types that
have a data field and a status field. They work in a similar fashion to
database/sql. The second is to use a pointer to a pointer.

    var foo pgtype.Varchar
    var bar *string
    err := conn.QueryRow("select foo, bar from widgets where id=$1", 42).Scan(&foo, &bar)
    if err != nil {
        return err
    }

Array Mapping

pgx maps between int16, int32, int64, float32, float64, and string Go slices
and the equivalent PostgreSQL array type. Go slices of native types do not
support nulls, so if a PostgreSQL array that contains a null is read into a
native Go slice an error will occur. The pgtype package includes many more
array types for PostgreSQL types that do not directly map to native Go types.

JSON and JSONB Mapping

pgx includes built-in support to marshal and unmarshal between Go types and
the PostgreSQL JSON and JSONB.

Inet and CIDR Mapping

pgx encodes from net.IPNet to and from inet and cidr PostgreSQL types. In
addition, as a convenience pgx will encode from a net.IP; it will assume a /32
netmask for IPv4 and a /128 for IPv6.

Custom Type Support

pgx includes support for the common data types like integers, floats, strings,
dates, and times that have direct mappings between Go and SQL. In addition,
pgx uses the github.com/jackc/pgx/pgtype library to support more types. See
documention for that library for instructions on how to implement custom
types.

See example_custom_type_test.go for an example of a custom type for the
PostgreSQL point type.

pgx also includes support for custom types implementing the database/sql.Scanner
and database/sql/driver.Valuer interfaces.

If pgx does cannot natively encode a type and that type is a renamed type (e.g.
type MyTime time.Time) pgx will attempt to encode the underlying type. While
this is usually desired behavior it can produce suprising behavior if one the
underlying type and the renamed type each implement database/sql interfaces and
the other implements pgx interfaces. It is recommended that this situation be
avoided by implementing pgx interfaces on the renamed type.

Raw Bytes Mapping

[]byte passed as arguments to Query, QueryRow, and Exec are passed unmodified
to PostgreSQL.

Transactions

Transactions are started by calling Begin or BeginEx. The BeginEx variant
can create a transaction with a specified isolation level.

    tx, err := conn.Begin()
    if err != nil {
        return err
    }
    // Rollback is safe to call even if the tx is already closed, so if
    // the tx commits successfully, this is a no-op
    defer tx.Rollback()

    _, err = tx.Exec("insert into foo(id) values (1)")
    if err != nil {
        return err
    }

    err = tx.Commit()
    if err != nil {
        return err
    }

Copy Protocol

Use CopyFrom to efficiently insert multiple rows at a time using the PostgreSQL
copy protocol. CopyFrom accepts a CopyFromSource interface. If the data is already
in a [][]interface{} use CopyFromRows to wrap it in a CopyFromSource interface. Or
implement CopyFromSource to avoid buffering the entire data set in memory.

    rows := [][]interface{}{
        {"John", "Smith", int32(36)},
        {"Jane", "Doe", int32(29)},
    }

    copyCount, err := conn.CopyFrom(
        pgx.Identifier{"people"},
        []string{"first_name", "last_name", "age"},
        pgx.CopyFromRows(rows),
    )

CopyFrom can be faster than an insert with as few as 5 rows.

Listen and Notify

pgx can listen to the PostgreSQL notification system with the
WaitForNotification function. It takes a maximum time to wait for a
notification.

    err := conn.Listen("channelname")
    if err != nil {
        return nil
    }

    if notification, err := conn.WaitForNotification(time.Second); err != nil {
        // do something with notification
    }

TLS

The pgx ConnConfig struct has a TLSConfig field. If this field is
nil, then TLS will be disabled. If it is present, then it will be used to
configure the TLS connection. This allows total configuration of the TLS
connection.

Logging

pgx defines a simple logger interface. Connections optionally accept a logger
that satisfies this interface. Set LogLevel to control logging verbosity.
Adapters for github.com/inconshreveable/log15, github.com/sirupsen/logrus, and
the testing log are provided in the log directory.
*/
package pgx
<|endoftext|>


<commit_before>package main

import (
	"github.com/awalterschulze/gographviz"
	"io/ioutil"
)

type Entity struct {
	name         string
	Entities     []*Entity
	VOs          []*ValueObject
	Refs         []*Entity
	callEntities []*Entity
}

type ValueObject struct {
	name string
}

type Repository struct {
	name string
	For  *Entity
}
type Provider struct {
	name string
}
type SubDomain struct {
	ARs       map[string]*Entity
	Repos     map[string]*Repository
	Providers map[string]*Provider
	es        map[string]*Entity
	vos       map[string]*ValueObject
}
type Model struct {
	SubDomains map[string]*SubDomain
}

func (model *Model) Validate() bool {
	for key := range model.SubDomains {
		if !model.SubDomains[key].Validate() {
			return false
		}
	}
	return true
}

func (model *Model) Compare(other *Model) bool {
	if len(model.SubDomains) != len(model.SubDomains) {
		return false
	}

	for key := range model.SubDomains {
		ar := model.SubDomains[key]
		if !ar.Compare(other.SubDomains[key]) {
			return false
		}
	}

	return true
}

func (subDomain *SubDomain) Validate() bool {
	for key := range subDomain.ARs {
		ar := subDomain.ARs[key]
		for _, cEntity := range ar.callEntities {
			if _, ok := subDomain.ARs[cEntity.name]; !ok {
				return false
			}
		}
	}
	return true
}

func (subDomain *SubDomain) Compare(other *SubDomain) bool {
	if len(subDomain.ARs) != len(other.ARs) {
		return false
	}
	if len(subDomain.Repos) != len(other.Repos) {
		return false
	}
	for key := range subDomain.ARs {
		ar := subDomain.ARs[key]
		if !ar.Compare(other.ARs[key]) {
			return false
		}
	}
	for key := range subDomain.Repos {
		repo := subDomain.Repos[key]
		if !repo.Compare(other.Repos[key]) {
			return false
		}
	}
	return true
}

func (subDomain *SubDomain) addNode(cms *CommentMappingList, name, comment string) {
	for _, cm := range *cms {
		if cm.comment == comment {
			cm.mapping(subDomain, name)
			break
		}
	}
}

func (subDomain *SubDomain) addRelations(src string, dsts []string) {
	if ar, ok := subDomain.ARs[src]; ok {
		subDomain.addAggregateRootRelations(ar,dsts )
	}
	if entity, ok := subDomain.es[src]; ok {
		subDomain.addEntityRelations(entity,dsts)
	}
	if repo, ok := subDomain.Repos[src]; ok {
		subDomain.addRepoRelations(repo,dsts)
	}
}
func (subDomain *SubDomain) addRepoRelations( repo *Repository, dsts []string) {
	for _, dst := range dsts {
		repo.For = subDomain.ARs[dst]
	}
}
func (subDomain *SubDomain) addEntityRelations(entity *Entity,dsts []string) {
	for _, dst := range dsts {
		if et, ok := subDomain.es[dst]; ok {
			entity.Entities = append(entity.Entities, et)
		}
		if vo, ok := subDomain.vos[dst]; ok {
			entity.VOs = append(entity.VOs, vo)
		}
	}
}
func (subDomain *SubDomain) addAggregateRootRelations(ar *Entity,dsts []string) {
	for _, dst := range dsts {
		if ref, ok := subDomain.ARs[dst]; ok {
			ar.Refs = append(ar.Refs, ref)
		}
		if et, ok := subDomain.es[dst]; ok {
			ar.Entities = append(ar.Entities, et)
		}
		if vo, ok := subDomain.vos[dst]; ok {
			ar.VOs = append(ar.VOs, vo)
		}
	}
}

func (entity *Entity) findEntity(name string) (*Entity, bool) {
	if entity.name == name {
		return entity, true
	} else {
		for _, et := range entity.Entities {
			if finded, ok := et.findEntity(name); ok {
				return finded, true
			}
		}
	}
	return nil, false
}

func (entity *Entity) Compare(other *Entity) bool {
	if len(entity.Entities) != len(other.Entities) {
		return false
	}
	if len(entity.VOs) != len(other.VOs) {
		return false
	}
	em := make(map[string]*Entity)
	for _, childEntity := range entity.Entities {
		em[childEntity.name] = childEntity
	}
	for _, childEntity := range other.Entities {
		if !em[childEntity.name].Compare(childEntity) {
			return false
		}
	}
	vom := make(map[string]*ValueObject)
	for _, vo := range entity.VOs {
		vom[vo.name] = vo
	}
	for _, vo := range other.VOs {
		if _, ok := vom[vo.name]; !ok {
			return false
		}
	}
	return true
}

func (repo *Repository) Compare(other *Repository) bool {
	return repo.For.Compare(other.For)
}

func createSubDomain() *SubDomain {
	return &SubDomain{
		ARs:       make(map[string]*Entity),
		Repos:     make(map[string]*Repository),
		Providers: make(map[string]*Provider),
		es:        make(map[string]*Entity),
		vos:       make(map[string]*ValueObject),
	}
}

type CommentMapping struct {
	comment string
	mapping func(domain *SubDomain, name string)
}

type CommentMappingList []*CommentMapping

var addAggregateRootFunc = func(subDomain *SubDomain, name string) {
	subDomain.ARs[name] = &Entity{name: name}
}
var addEntityFunc = func(subDomain *SubDomain, name string) {
	subDomain.es[name] = &Entity{name: name}
}
var addValueObjectFunc = func(subDomain *SubDomain, name string) {
	subDomain.vos[name] = &ValueObject{name: name}
}

var addRepoFunc = func(subDomain *SubDomain, name string) {
	subDomain.Repos[name] = &Repository{name: name}
}
var addProviderFunc = func(subDomain *SubDomain, name string) {
	subDomain.Providers[name] = &Provider{name: name}
}

func InitCommentMapping() *CommentMappingList {
	return &CommentMappingList{
		{comment: "AR", mapping: addAggregateRootFunc},
		{comment: "E", mapping: addEntityFunc},
		{comment: "VO", mapping: addValueObjectFunc},
		{comment: "Repo", mapping: addRepoFunc},
		{comment: "Provider", mapping: addProviderFunc},
	}
}

func edgesKey(edges map[string][]*gographviz.Edge) []string {
	result := make([]string, 0)
	for key := range edges {
		result = append(result, key)
	}
	return result
}

func Parse(dotFile string) *Model {
	fbuf, _ := ioutil.ReadFile(dotFile)
	g, _ := gographviz.Read(fbuf)

	c2pMap := make(map[string]string)
	p2c := g.Relations.ParentToChildren

	subDomains := make(map[string]*SubDomain)

	if _, ok := p2c["g"]; ok {
		for key := range p2c["g"] {
			c2pMap[key] = "subdomain"
		}
		subDomains["subdomain"] = createSubDomain()
	} else {
		for clusterKey := range p2c {
			subDomainName := g.SubGraphs.SubGraphs[clusterKey].Attrs["label"]
			for key := range p2c[clusterKey] {
				c2pMap[key] = subDomainName
			}
			subDomains[subDomainName] = createSubDomain()
		}
	}
	cms := InitCommentMapping()
	for _, node := range g.Nodes.Nodes {
		subDomain := subDomains[c2pMap[node.Name]]
		subDomain.addNode(cms, node.Name, node.Attrs["comment"])
	}

	for key := range g.Edges.SrcToDsts {
		edgeKeys := edgesKey(g.Edges.SrcToDsts[key])
		subDomain := subDomains[c2pMap[key]]
		subDomain.addRelations(key, edgeKeys)
	}

	return &Model{SubDomains: subDomains}
}
<commit_msg>refactor to dsl<commit_after>package main

import (
	"github.com/awalterschulze/gographviz"
	"io/ioutil"
)

type Entity struct {
	name         string
	Entities     []*Entity
	VOs          []*ValueObject
	Refs         []*Entity
	callEntities []*Entity
}

type ValueObject struct {
	name string
}

type Repository struct {
	name string
	For  *Entity
}
type Provider struct {
	name string
}
type SubDomain struct {
	ARs       map[string]*Entity
	Repos     map[string]*Repository
	Providers map[string]*Provider
	es        map[string]*Entity
	vos       map[string]*ValueObject
}
type Model struct {
	SubDomains map[string]*SubDomain
}

func (model *Model) Validate() bool {
	for key := range model.SubDomains {
		if !model.SubDomains[key].Validate() {
			return false
		}
	}
	return true
}

func (model *Model) Compare(other *Model) bool {
	if len(model.SubDomains) != len(model.SubDomains) {
		return false
	}

	for key := range model.SubDomains {
		ar := model.SubDomains[key]
		if !ar.Compare(other.SubDomains[key]) {
			return false
		}
	}

	return true
}

func (subDomain *SubDomain) Validate() bool {
	for key := range subDomain.ARs {
		ar := subDomain.ARs[key]
		for _, cEntity := range ar.callEntities {
			if _, ok := subDomain.ARs[cEntity.name]; !ok {
				return false
			}
		}
	}
	return true
}

func (subDomain *SubDomain) Compare(other *SubDomain) bool {
	if len(subDomain.ARs) != len(other.ARs) {
		return false
	}
	if len(subDomain.Repos) != len(other.Repos) {
		return false
	}
	for key := range subDomain.ARs {
		ar := subDomain.ARs[key]
		if !ar.Compare(other.ARs[key]) {
			return false
		}
	}
	for key := range subDomain.Repos {
		repo := subDomain.Repos[key]
		if !repo.Compare(other.Repos[key]) {
			return false
		}
	}
	return true
}

func (subDomain *SubDomain) addNode(cms *CommentMappingList, name, comment string) {
	for _, cm := range *cms {
		if cm.comment == comment {
			cm.mapping(subDomain, name)
			break
		}
	}
}

type SubDomainWhenThen struct {
	subDomain *SubDomain
	isMatch   bool
	current   interface{}
	src       string
	dsts      []string
}

func (subDomain *SubDomain) given(src string, dsts []string) *SubDomainWhenThen {
	return &SubDomainWhenThen{
		subDomain: subDomain,
		src:       src,
		dsts:      dsts,
	}
}

func (whenThen *SubDomainWhenThen) when(fined interface{}, ok bool) *SubDomainWhenThen {
	whenThen.isMatch = ok
	if ok {
		whenThen.current = fined
	}

	return whenThen
}

func (whenThen *SubDomainWhenThen) whenRepo() *SubDomainWhenThen {
	repo, ok := whenThen.subDomain.Repos[whenThen.src]
	return whenThen.when(repo, ok)
}

func (whenThen *SubDomainWhenThen) whenEntity() *SubDomainWhenThen {
	entity, ok := whenThen.subDomain.es[whenThen.src]
	return whenThen.when(entity, ok)
}
func (whenThen *SubDomainWhenThen) whenAggregateRoot() *SubDomainWhenThen {
	ar, ok := whenThen.subDomain.ARs[whenThen.src]
	return whenThen.when(ar, ok)
}

func (whenThen *SubDomainWhenThen) thenAdd(addRelations func(interface{}, []string)) *SubDomainWhenThen {
	if whenThen.isMatch {
		addRelations(whenThen.current, whenThen.dsts)
	}
	return whenThen
}

func (subDomain *SubDomain) addRelations(src string, dsts []string) {
	subDomain.given(src, dsts).
		whenAggregateRoot().thenAdd(subDomain.addAggregateRootRelations).
		whenEntity().thenAdd(subDomain.addEntityRelations).
		whenRepo().thenAdd(subDomain.addRepoRelations)
}

func (subDomain *SubDomain) addRepoRelations(repo interface{}, dsts []string) {
	for _, dst := range dsts {
		repo.(*Repository).For = subDomain.ARs[dst]
	}
}
func (subDomain *SubDomain) addEntityRelations(entity interface{}, dsts []string) {
	for _, dst := range dsts {
		_entity := entity.(*Entity)
		if et, ok := subDomain.es[dst]; ok {
			_entity.Entities = append(_entity.Entities, et)
		}
		if vo, ok := subDomain.vos[dst]; ok {
			_entity.VOs = append(_entity.VOs, vo)
		}
	}
}
func (subDomain *SubDomain) addAggregateRootRelations(ar interface{}, dsts []string) {
	for _, dst := range dsts {
		_ar := ar.(*Entity)
		if ref, ok := subDomain.ARs[dst]; ok {
			_ar.Refs = append(_ar.Refs, ref)
		}
		if et, ok := subDomain.es[dst]; ok {
			_ar.Entities = append(_ar.Entities, et)
		}
		if vo, ok := subDomain.vos[dst]; ok {
			_ar.VOs = append(_ar.VOs, vo)
		}
	}
}

func (entity *Entity) findEntity(name string) (*Entity, bool) {
	if entity.name == name {
		return entity, true
	} else {
		for _, et := range entity.Entities {
			if finded, ok := et.findEntity(name); ok {
				return finded, true
			}
		}
	}
	return nil, false
}

func (entity *Entity) Compare(other *Entity) bool {
	if len(entity.Entities) != len(other.Entities) {
		return false
	}
	if len(entity.VOs) != len(other.VOs) {
		return false
	}
	em := make(map[string]*Entity)
	for _, childEntity := range entity.Entities {
		em[childEntity.name] = childEntity
	}
	for _, childEntity := range other.Entities {
		if !em[childEntity.name].Compare(childEntity) {
			return false
		}
	}
	vom := make(map[string]*ValueObject)
	for _, vo := range entity.VOs {
		vom[vo.name] = vo
	}
	for _, vo := range other.VOs {
		if _, ok := vom[vo.name]; !ok {
			return false
		}
	}
	return true
}

func (repo *Repository) Compare(other *Repository) bool {
	return repo.For.Compare(other.For)
}

func createSubDomain() *SubDomain {
	return &SubDomain{
		ARs:       make(map[string]*Entity),
		Repos:     make(map[string]*Repository),
		Providers: make(map[string]*Provider),
		es:        make(map[string]*Entity),
		vos:       make(map[string]*ValueObject),
	}
}

type CommentMapping struct {
	comment string
	mapping func(domain *SubDomain, name string)
}

type CommentMappingList []*CommentMapping

var addAggregateRootFunc = func(subDomain *SubDomain, name string) {
	subDomain.ARs[name] = &Entity{name: name}
}
var addEntityFunc = func(subDomain *SubDomain, name string) {
	subDomain.es[name] = &Entity{name: name}
}
var addValueObjectFunc = func(subDomain *SubDomain, name string) {
	subDomain.vos[name] = &ValueObject{name: name}
}

var addRepoFunc = func(subDomain *SubDomain, name string) {
	subDomain.Repos[name] = &Repository{name: name}
}
var addProviderFunc = func(subDomain *SubDomain, name string) {
	subDomain.Providers[name] = &Provider{name: name}
}

func InitCommentMapping() *CommentMappingList {
	return &CommentMappingList{
		{comment: "AR", mapping: addAggregateRootFunc},
		{comment: "E", mapping: addEntityFunc},
		{comment: "VO", mapping: addValueObjectFunc},
		{comment: "Repo", mapping: addRepoFunc},
		{comment: "Provider", mapping: addProviderFunc},
	}
}

func edgesKey(edges map[string][]*gographviz.Edge) []string {
	result := make([]string, 0)
	for key := range edges {
		result = append(result, key)
	}
	return result
}

func Parse(dotFile string) *Model {
	fbuf, _ := ioutil.ReadFile(dotFile)
	g, _ := gographviz.Read(fbuf)

	c2pMap := make(map[string]string)
	p2c := g.Relations.ParentToChildren

	subDomains := make(map[string]*SubDomain)

	if _, ok := p2c["g"]; ok {
		for key := range p2c["g"] {
			c2pMap[key] = "subdomain"
		}
		subDomains["subdomain"] = createSubDomain()
	} else {
		for clusterKey := range p2c {
			subDomainName := g.SubGraphs.SubGraphs[clusterKey].Attrs["label"]
			for key := range p2c[clusterKey] {
				c2pMap[key] = subDomainName
			}
			subDomains[subDomainName] = createSubDomain()
		}
	}
	cms := InitCommentMapping()
	for _, node := range g.Nodes.Nodes {
		subDomain := subDomains[c2pMap[node.Name]]
		subDomain.addNode(cms, node.Name, node.Attrs["comment"])
	}

	for key := range g.Edges.SrcToDsts {
		edgeKeys := edgesKey(g.Edges.SrcToDsts[key])
		subDomain := subDomains[c2pMap[key]]
		subDomain.addRelations(key, edgeKeys)
	}

	return &Model{SubDomains: subDomains}
}
<|endoftext|>


<commit_before>package main

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecs"
)

type ecsClient struct {
	ecs *ecs.ECS
}

func newECS(region string, sess *session.Session) *ecsClient {
	return &ecsClient{ecs.New(sess, aws.NewConfig().WithRegion(region))}
}

func (e *ecsClient) describeCluster(cluster string) (*ecs.Cluster, error) {
	params := &ecs.DescribeClustersInput{
		Clusters: []*string{
			aws.String(cluster),
		},
	}
	resp, err := e.ecs.DescribeClusters(params)
	if err != nil {
		return nil, err
	}
	return resp.Clusters[0], nil
}

func (e *ecsClient) listContainerInstances(cluster string) ([]*string, error) {
	params := &ecs.ListContainerInstancesInput{
		Cluster: aws.String(cluster),
	}
	resp, err := e.ecs.ListContainerInstances(params)
	if err != nil {
		return nil, err
	}
	return resp.ContainerInstanceArns, nil
}

func (e *ecsClient) describeContainerInstances(cluster string, arns []*string) ([]*ecs.ContainerInstance, error) {
	params := &ecs.DescribeContainerInstancesInput{
		ContainerInstances: arns,
		Cluster:            aws.String(cluster),
	}
	resp, err := e.ecs.DescribeContainerInstances(params)
	if err != nil {
		return nil, err
	}
	return resp.ContainerInstances, nil
}

func (e *ecsClient) listServices(cluster string) ([]*string, error) {
	params := &ecs.ListServicesInput{
		Cluster: aws.String(cluster),
	}
	resp, err := e.ecs.ListServices(params)
	if err != nil {
		return nil, err
	}
	return resp.ServiceArns, nil
}

func (e *ecsClient) describeServices(cluster string, arns []*string) ([]*ecs.Service, error) {
	params := &ecs.DescribeServicesInput{
		Services: arns,
		Cluster:  aws.String(cluster),
	}
	resp, err := e.ecs.DescribeServices(params)
	if err != nil {
		return nil, err
	}
	return resp.Services, nil
}

func (e *ecsClient) listTasks(cluster string) ([]*string, error) {
	params := &ecs.ListTasksInput{
		Cluster: aws.String(cluster),
		//	ContainerInstance: aws.String("String"),
		//	DesiredStatus:     aws.String("DesiredStatus"),
		//		Family:            aws.String("String"),
		//		MaxResults:        aws.Int64(1),
		//		NextToken:         aws.String("String"),
		//		ServiceName:       aws.String("String"),
		//		StartedBy:         aws.String("String"),
	}
	resp, err := e.ecs.ListTasks(params)
	if err != nil {
		return nil, err
	}
	return resp.TaskArns, nil
}

func (e *ecsClient) describeTasks(cluster string, arns []*string) ([]*ecs.Task, error) {
	params := &ecs.DescribeTasksInput{
		Cluster: aws.String(cluster),
		Tasks:   arns,
	}
	tasks, err := e.ecs.DescribeTasks(params)
	if err != nil {
		return nil, err
	}
	return tasks.Tasks, nil
}

func (e *ecsClient) describeTaskDefinition(arn *string) (*ecs.TaskDefinition, error) {
	params := &ecs.DescribeTaskDefinitionInput{
		TaskDefinition: arn,
	}
	resp, err := e.ecs.DescribeTaskDefinition(params)
	if err != nil {
		return nil, err
	}
	return resp.TaskDefinition, nil
}
<commit_msg>Verbose errors if cluster was not found<commit_after>package main

import (
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/session"
	"github.com/aws/aws-sdk-go/service/ecs"
	"fmt"
)

type ecsClient struct {
	ecs *ecs.ECS
}

func newECS(region string, sess *session.Session) *ecsClient {
	return &ecsClient{ecs.New(sess, aws.NewConfig().WithRegion(region))}
}

func (e *ecsClient) describeCluster(cluster string) (*ecs.Cluster, error) {
	params := &ecs.DescribeClustersInput{
		Clusters: []*string{
			aws.String(cluster),
		},
	}
	resp, err := e.ecs.DescribeClusters(params)
	if err != nil {
		return nil, err
	}
	if len(resp.Clusters) == 0 {
		return nil, fmt.Errorf("Cluster %s not found. Did you specify the correct cluster name for your region?", cluster)
	}
	return resp.Clusters[0], nil
}

func (e *ecsClient) listContainerInstances(cluster string) ([]*string, error) {
	params := &ecs.ListContainerInstancesInput{
		Cluster: aws.String(cluster),
	}
	resp, err := e.ecs.ListContainerInstances(params)
	if err != nil {
		return nil, err
	}
	return resp.ContainerInstanceArns, nil
}

func (e *ecsClient) describeContainerInstances(cluster string, arns []*string) ([]*ecs.ContainerInstance, error) {
	params := &ecs.DescribeContainerInstancesInput{
		ContainerInstances: arns,
		Cluster:            aws.String(cluster),
	}
	resp, err := e.ecs.DescribeContainerInstances(params)
	if err != nil {
		return nil, err
	}
	return resp.ContainerInstances, nil
}

func (e *ecsClient) listServices(cluster string) ([]*string, error) {
	params := &ecs.ListServicesInput{
		Cluster: aws.String(cluster),
	}
	resp, err := e.ecs.ListServices(params)
	if err != nil {
		return nil, err
	}
	return resp.ServiceArns, nil
}

func (e *ecsClient) describeServices(cluster string, arns []*string) ([]*ecs.Service, error) {
	params := &ecs.DescribeServicesInput{
		Services: arns,
		Cluster:  aws.String(cluster),
	}
	resp, err := e.ecs.DescribeServices(params)
	if err != nil {
		return nil, err
	}
	return resp.Services, nil
}

func (e *ecsClient) listTasks(cluster string) ([]*string, error) {
	params := &ecs.ListTasksInput{
		Cluster: aws.String(cluster),
		//	ContainerInstance: aws.String("String"),
		//	DesiredStatus:     aws.String("DesiredStatus"),
		//		Family:            aws.String("String"),
		//		MaxResults:        aws.Int64(1),
		//		NextToken:         aws.String("String"),
		//		ServiceName:       aws.String("String"),
		//		StartedBy:         aws.String("String"),
	}
	resp, err := e.ecs.ListTasks(params)
	if err != nil {
		return nil, err
	}
	return resp.TaskArns, nil
}

func (e *ecsClient) describeTasks(cluster string, arns []*string) ([]*ecs.Task, error) {
	params := &ecs.DescribeTasksInput{
		Cluster: aws.String(cluster),
		Tasks:   arns,
	}
	tasks, err := e.ecs.DescribeTasks(params)
	if err != nil {
		return nil, err
	}
	return tasks.Tasks, nil
}

func (e *ecsClient) describeTaskDefinition(arn *string) (*ecs.TaskDefinition, error) {
	params := &ecs.DescribeTaskDefinitionInput{
		TaskDefinition: arn,
	}
	resp, err := e.ecs.DescribeTaskDefinition(params)
	if err != nil {
		return nil, err
	}
	return resp.TaskDefinition, nil
}
<|endoftext|>


<commit_before>package env

import (
	"log"
	"os"
	"strconv"
	"time"
)

var parseLog = func(error) {}

// SetParseLog sets up a logger for parse errors on environment variables with
// default values configured. The default value will be returned on a parse
// failure but the provided log function will also be called.
//
// To set the log function, as the first var in your var block put
//
// 	_ = env.SetParseLog(func(err error) {
// 		// custom logging code goes here
// 	})
//
// This way the log function will be initialized before calls to env functions
// that parse, such as Int and Duration.
//
// The default log function is a nop (does not log anything).
func SetParseLog(logFunc func(error)) struct{} {
	parseLog = logFunc
	return struct{}{}
}

// String retrieves the string value of the environment variable named by the
// key. If the variable is present in the environment the value (which may be
// empty) is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
func String(key, value, description string) string {
	if v, ok := os.LookupEnv(key); ok {
		return v
	}
	return value
}

// MustString retrieves the string value of the environment variable named by
// the key. If the variable is present in the environment the value (which may
// be empty) is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustString(key, description string) string {
	v, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set", key)
	}
	return v
}

// Int retrieves the int value of the environment variable named by the key. If
// the variable is present in the environment and the value successfully parses
// into an int then that int is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Int(key string, value int, description string) int {
	if s, ok := os.LookupEnv(key); ok {
		v, err := strconv.Atoi(s)
		if err == nil {
			return v
		}
		parseLog(err)
	}
	return value
}

// MustInt retrieves the int value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an int then that int is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustInt(key, description string) int {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set", key)
	}
	v, err := strconv.Atoi(s)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return v
}

// Int64 retrieves the int64 value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an int64 then that int64 is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Int64(key string, value int64, description string) int64 {
	if s, ok := os.LookupEnv(key); ok {
		v, err := strconv.ParseInt(s, 10, 0)
		if err == nil {
			return v
		}
		parseLog(err)
	}
	return value
}

// MustInt64 retrieves the int64 value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an int64 then that int64 is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustInt64(key, description string) int64 {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set", key)
	}
	v, err := strconv.ParseInt(s, 10, 0)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return v
}

// Bool retrieves the bool value of the environment variable named by the key.
// If the variable is not present in the environment then the returned bool is
// false. Also, if the variable is present in the environment and is set to any
// of the strings "0", "false", "False", "f", "F", "n", or "N", then the
// returned bool will be false.
// If the variable is present and set to anything not in the false values
// listed above, then the returned bool will be true.
func Bool(key string, value bool, description string) bool {
	if s, ok := os.LookupEnv(key); ok {
		switch s {
		case "0", "false", "False", "f", "F", "n", "N":
			return false
		}
		return true
	}
	return value
}

// Duration retrieves the time.Duration value of the environment variable named
// by the key. If the variable is present in the environment and the value
// successfully parses into a time.Duration then that time.Duration value is
// returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Duration(key string, value time.Duration, description string) time.Duration {
	if s, ok := os.LookupEnv(key); ok {
		v, err := time.ParseDuration(s)
		if err == nil {
			return v
		}
		parseLog(err)
	}
	return value
}

// MustDuration retrieves the time.Duration value of the environment variable
// named by the key. If the variable is present in the environment and the
// value successfully parses into an time.Duration then that time.Duration is
// returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustDuration(key, description string) time.Duration {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set", key)
	}
	v, err := time.ParseDuration(s)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return v
}

// Uint retrieves the uint value of the environment variable named by the key.
// If the variable is present in the environment and the value successfully
// parses into an uint then that uint is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Uint(key string, value uint, description string) uint {
	if s, ok := os.LookupEnv(key); ok {
		v, err := strconv.ParseUint(s, 10, 0)
		if err == nil {
			return uint(v)
		}
		parseLog(err)
	}
	return value
}

// MustUint retrieves the uint value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an uint then that uint is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustUint(key, description string) uint {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set")
	}
	v, err := strconv.ParseUint(s, 10, 0)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return uint(v)
}

// Uint64 retrieves the uint64 value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an uint64 then that uint64 is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Uint64(key string, value uint64, description string) uint64 {
	if s, ok := os.LookupEnv(key); ok {
		v, err := strconv.ParseUint(s, 10, 0)
		if err == nil {
			return v
		}
		parseLog(err)
	}
	return value
}

// MustUint64 retrieves the uint64 value of the environment variable named by
// the key. If the variable is present in the environment and the value
// successfully parses into an uint64 then that uint64 is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustUint64(key, description string) uint64 {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set")
	}
	v, err := strconv.ParseUint(s, 10, 0)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return v
}
<commit_msg>env: s/description/usage/g<commit_after>package env

import (
	"log"
	"os"
	"strconv"
	"time"
)

var parseLog = func(error) {}

// SetParseLog sets up a logger for parse errors on environment variables with
// default values configured. The default value will be returned on a parse
// failure but the provided log function will also be called.
//
// To set the log function, as the first var in your var block put
//
// 	_ = env.SetParseLog(func(err error) {
// 		// custom logging code goes here
// 	})
//
// This way the log function will be initialized before calls to env functions
// that parse, such as Int and Duration.
//
// The default log function is a nop (does not log anything).
func SetParseLog(logFunc func(error)) struct{} {
	parseLog = logFunc
	return struct{}{}
}

// String retrieves the string value of the environment variable named by the
// key. If the variable is present in the environment the value (which may be
// empty) is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
func String(key, value, usage string) string {
	if v, ok := os.LookupEnv(key); ok {
		return v
	}
	return value
}

// MustString retrieves the string value of the environment variable named by
// the key. If the variable is present in the environment the value (which may
// be empty) is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustString(key, usage string) string {
	v, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set", key)
	}
	return v
}

// Int retrieves the int value of the environment variable named by the key. If
// the variable is present in the environment and the value successfully parses
// into an int then that int is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Int(key string, value int, usage string) int {
	if s, ok := os.LookupEnv(key); ok {
		v, err := strconv.Atoi(s)
		if err == nil {
			return v
		}
		parseLog(err)
	}
	return value
}

// MustInt retrieves the int value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an int then that int is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustInt(key, usage string) int {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set", key)
	}
	v, err := strconv.Atoi(s)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return v
}

// Int64 retrieves the int64 value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an int64 then that int64 is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Int64(key string, value int64, usage string) int64 {
	if s, ok := os.LookupEnv(key); ok {
		v, err := strconv.ParseInt(s, 10, 0)
		if err == nil {
			return v
		}
		parseLog(err)
	}
	return value
}

// MustInt64 retrieves the int64 value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an int64 then that int64 is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustInt64(key, usage string) int64 {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set", key)
	}
	v, err := strconv.ParseInt(s, 10, 0)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return v
}

// Bool retrieves the bool value of the environment variable named by the key.
// If the variable is not present in the environment then the returned bool is
// false. Also, if the variable is present in the environment and is set to any
// of the strings "0", "false", "False", "f", "F", "n", or "N", then the
// returned bool will be false.
// If the variable is present and set to anything not in the false values
// listed above, then the returned bool will be true.
func Bool(key string, value bool, usage string) bool {
	if s, ok := os.LookupEnv(key); ok {
		switch s {
		case "0", "false", "False", "f", "F", "n", "N":
			return false
		}
		return true
	}
	return value
}

// Duration retrieves the time.Duration value of the environment variable named
// by the key. If the variable is present in the environment and the value
// successfully parses into a time.Duration then that time.Duration value is
// returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Duration(key string, value time.Duration, usage string) time.Duration {
	if s, ok := os.LookupEnv(key); ok {
		v, err := time.ParseDuration(s)
		if err == nil {
			return v
		}
		parseLog(err)
	}
	return value
}

// MustDuration retrieves the time.Duration value of the environment variable
// named by the key. If the variable is present in the environment and the
// value successfully parses into an time.Duration then that time.Duration is
// returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustDuration(key, usage string) time.Duration {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set", key)
	}
	v, err := time.ParseDuration(s)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return v
}

// Uint retrieves the uint value of the environment variable named by the key.
// If the variable is present in the environment and the value successfully
// parses into an uint then that uint is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Uint(key string, value uint, usage string) uint {
	if s, ok := os.LookupEnv(key); ok {
		v, err := strconv.ParseUint(s, 10, 0)
		if err == nil {
			return uint(v)
		}
		parseLog(err)
	}
	return value
}

// MustUint retrieves the uint value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an uint then that uint is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustUint(key, usage string) uint {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set")
	}
	v, err := strconv.ParseUint(s, 10, 0)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return uint(v)
}

// Uint64 retrieves the uint64 value of the environment variable named by the
// key. If the variable is present in the environment and the value
// successfully parses into an uint64 then that uint64 is returned.
// Otherwise the returned value will be the default value specified by the
// value argument.
// If the parse fails the logger set in SetParseLog will be called.
func Uint64(key string, value uint64, usage string) uint64 {
	if s, ok := os.LookupEnv(key); ok {
		v, err := strconv.ParseUint(s, 10, 0)
		if err == nil {
			return v
		}
		parseLog(err)
	}
	return value
}

// MustUint64 retrieves the uint64 value of the environment variable named by
// the key. If the variable is present in the environment and the value
// successfully parses into an uint64 then that uint64 is returned.
// Otherwise this function logs an error to the default log and causes an
// os.Exit.
func MustUint64(key, usage string) uint64 {
	s, ok := os.LookupEnv(key)
	if !ok {
		log.Fatalf("env: %v not set")
	}
	v, err := strconv.ParseUint(s, 10, 0)
	if err != nil {
		log.Fatalf("env: %v parse error: %v", key, err)
	}
	return v
}
<|endoftext|>


<commit_before>package apex

import (
	"encoding/json"
	"io/ioutil"
)

// environment map, loaded from .env.json injected into the Lambda function's container.
var environ map[string]string

// Getenv retrieves the value of the environment variable named by the key.
func Getenv(name string) string {
	if environ == nil {
		b, err := ioutil.ReadFile(".env.json")
		if err != nil {
			return ""
		}

		if err := json.Unmarshal(b, &environ); err != nil {
			return ""
		}
	}

	return environ[name]
}
<commit_msg>remove Getenv(), prime via os.Setenv() instead<commit_after>package apex

import (
	"encoding/json"
	"io/ioutil"
	"os"
)

func init() {
	env := make(map[string]string)

	b, err := ioutil.ReadFile(".env.json")
	if err != nil {
		return
	}

	if err := json.Unmarshal(b, &env); err != nil {
		return
	}

	for k, v := range env {
		os.Setenv(k, v)
	}
}
<|endoftext|>


<commit_before>/*
Package FDA implements Golang bindings for the OpenFDA API.

Copyright and license is described in LICENSE within this package.

To get an API key, which permits many more requests per hour than with
unauthenticated API use, please see https://open.fda.gov/api/reference/#authentication

To learn how to craft optimal queries for this API, please see
https://open.fda.gov/api/reference/#query-syntax
*/
package fda

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
)

const (
	LibraryVersion = "0.0.1"

	// This is the FDA API endpoint
	BaseURL = "https://api.fda.gov"

	UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)"
)

type Client struct {
	// HTTP client used to communicate with the API
	client *http.Client

	// Base URL for API requests
	BaseURL *url.URL

	// User Agent used when communicating with the API
	UserAgent string

	// May be left blank, but requests permitted per hour dramatically higher w/valid key.
	APIKey string

	// Accept responses of this type. Defaults to JSON. Currently FDA only supports JSON.
	ResponseType string

	// For accessing functions of the API
	Drug   *DrugService
	Device *DeviceService
	Food   *FoodService
}

// NewClient returns a new API client. if a nil httpClient is
// provided, http.DefaultClient will be used.
func NewClient(httpClient *http.Client, apikey string) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(BaseURL)

	c := &Client{
		client:       httpClient,
		BaseURL:      baseURL,
		UserAgent:    UserAgent,
		APIKey:       apikey,
		ResponseType: `.json`, //Since JSON is the only supported output for now, in this version it is not user-configurable
	}

	c.Drug = &DrugService{client: c}
	c.Device = &DeviceService{client: c}
	c.Food = &FoodService{client: c}

	return c
}

// NewRequest creates an API request. A relative URL can be provided in endpoint,
// in which case it is resolved relative to the BaseURL of the Client.
func (c *Client) NewRequest(endpoint string, params url.Values, body string) (*http.Request, error) {
	if c.APIKey != "" {
		params.Add("api_key", c.APIKey)
	}

	rel, err := url.Parse(fmt.Sprint(endpoint, c.ResponseType, "?", params.Encode()))
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)
	q := u.Query()
	u.RawQuery = q.Encode()

	req, err := http.NewRequest("GET", u.String(), bytes.NewBufferString(body))
	if err != nil {
		return nil, err
	}

	req.Header.Add("User-Agent", c.UserAgent)
	return req, nil
}

// Do sends an API request and returns the API response. The API response is
// decoded and stored in the value pointed to by v, or returned as an error if
// an API error has occurred.
func (c *Client) Do(req *http.Request, v interface{}) (*Response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	err = CheckResponse(resp)
	if err != nil {
		return nil, err
	}

	//For debugging
	//buffer := &bytes.Buffer{}
	//buffer.ReadFrom(resp.Body)
	//fmt.Println(buffer.String())

	r := &Response{HTTPResponse: resp}
	if v != nil {
		// Our passed argument is now the value of r.Response
		r.Results = v
		// Decode the JSON into r.Data (which is our argument)
		err = json.NewDecoder(resp.Body).Decode(r)
	}
	return r, err
}

// search implements a generic search function that is broadly applicable to all OpenFDA Search endpoints
// but which may not cover all search use-cases. It is a convenience function to reduce code duplication
// for generic search services.
func (c *Client) search(endpoint, search string, limit, skip int, data interface{}) (*Meta, error) {
	params := url.Values{}
	params.Add("limit", strconv.Itoa(limit))
	params.Add("skip", strconv.Itoa(skip))
	if search != "" {
		params.Add("search", search)
	}

	req, err := c.NewRequest(endpoint, params, "")
	if err != nil {
		return &Meta{}, err
	}

	resp, err := c.Do(req, &data)
	if err != nil {
		return &Meta{}, fmt.Errorf("Search:err: %s", err)
	}

	return resp.Meta, nil
}

// Reponse resembles the data returned by the API
type Response struct {
	HTTPResponse *http.Response
	Response     interface{}
	Meta         *Meta
	Results      interface{}
}

// Meta represents information about the response. The Disclaimer and License
// appear to be boilerplate, but the Pagination data will be useful
// to assist in iterating over a dataset which contains greater than 100 items.
type Meta struct {
	Disclaimer  string
	License     string
	LastUpdated string     `json:"last_updated"`
	Pagination  Pagination `json:"results"`
}

// Pagination contains information about the returned data, including how many
// records were skipped (Skip), how many records were included (Limit), and
// how many total records exist (Total).
type Pagination struct {
	Skip  int
	Limit int
	Total int
}

// ErrorResponse represents a Response which contains an error and which
// satisfies the Error type
type ErrorResponse struct {
	HTTPResponse *http.Response
	Err          struct {
		StatusCode int
		Code       string
		Message    string
	} `json:"error"`
}

func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %d %v %v",
		r.HTTPResponse.Request.Method, r.HTTPResponse.Request.URL.String(),
		r.Err.StatusCode, r.Err.Code, r.Err.Message)
}

// CheckResponse checks the API response for error, and returns it
// if present. A response is considered an error if it has non-http.StatusOK
// code.
func CheckResponse(r *http.Response) error {
	if r.StatusCode == http.StatusOK {
		return nil
	}

	resp := new(ErrorResponse)
	resp.HTTPResponse = r

	err := json.NewDecoder(r.Body).Decode(resp)
	if err != nil {
		return fmt.Errorf("CheckResponse:error: %s", err.Error())
	}

	resp.Err.StatusCode = r.StatusCode

	return resp
}
<commit_msg>Stop exporting items that do not need to be exported to reduce the public API footprint.<commit_after>/*
Package FDA implements Golang bindings for the OpenFDA API.

Copyright and license is described in LICENSE within this package.

To get an API key, which permits many more requests per hour than with
unauthenticated API use, please see https://open.fda.gov/api/reference/#authentication

To learn how to craft optimal queries for this API, please see
https://open.fda.gov/api/reference/#query-syntax
*/
package fda

import (
	"bytes"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strconv"
)

const (
	LibraryVersion = "0.0.1"

	// This is the FDA API endpoint
	BaseURL = "https://api.fda.gov"

	UserAgent = "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0)"
)

type Client struct {
	// HTTP client used to communicate with the API
	client *http.Client

	// Base URL for API requests
	BaseURL *url.URL

	// User Agent used when communicating with the API
	UserAgent string

	// May be left blank, but requests permitted per hour dramatically higher w/valid key.
	APIKey string

	// Accept responses of this type. Defaults to JSON. Currently FDA only supports JSON.
	ResponseType string

	// For accessing functions of the API
	Drug   *DrugService
	Device *DeviceService
	Food   *FoodService
}

// NewClient returns a new API client. if a nil httpClient is
// provided, http.DefaultClient will be used.
func NewClient(httpClient *http.Client, apikey string) *Client {
	if httpClient == nil {
		httpClient = http.DefaultClient
	}
	baseURL, _ := url.Parse(BaseURL)

	c := &Client{
		client:       httpClient,
		BaseURL:      baseURL,
		UserAgent:    UserAgent,
		APIKey:       apikey,
		ResponseType: `.json`, //Since JSON is the only supported output for now, in this version it is not user-configurable
	}

	c.Drug = &DrugService{client: c}
	c.Device = &DeviceService{client: c}
	c.Food = &FoodService{client: c}

	return c
}

// NewRequest creates an API request. A relative URL can be provided in endpoint,
// in which case it is resolved relative to the BaseURL of the Client.
func (c *Client) NewRequest(endpoint string, params url.Values, body string) (*http.Request, error) {
	if c.APIKey != "" {
		params.Add("api_key", c.APIKey)
	}

	rel, err := url.Parse(fmt.Sprint(endpoint, c.ResponseType, "?", params.Encode()))
	if err != nil {
		return nil, err
	}

	u := c.BaseURL.ResolveReference(rel)
	q := u.Query()
	u.RawQuery = q.Encode()

	req, err := http.NewRequest("GET", u.String(), bytes.NewBufferString(body))
	if err != nil {
		return nil, err
	}

	req.Header.Add("User-Agent", c.UserAgent)
	return req, nil
}

// Do sends an API request and returns the API response. The API response is
// decoded and stored in the value pointed to by v, or returned as an error if
// an API error has occurred.
func (c *Client) Do(req *http.Request, v interface{}) (*response, error) {
	resp, err := c.client.Do(req)
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()

	err = checkResponse(resp)
	if err != nil {
		return nil, err
	}

	//For debugging
	//buffer := &bytes.Buffer{}
	//buffer.ReadFrom(resp.Body)
	//fmt.Println(buffer.String())

	r := &response{HTTPResponse: resp}
	if v != nil {
		// Our passed argument is now the value of r.Response
		r.Results = v
		// Decode the JSON into r.Data (which is our argument)
		err = json.NewDecoder(resp.Body).Decode(r)
	}
	return r, err
}

// search implements a generic search function that is broadly applicable to all OpenFDA Search endpoints
// but which may not cover all search use-cases. It is a convenience function to reduce code duplication
// for generic search services.
func (c *Client) search(endpoint, search string, limit, skip int, data interface{}) (*Meta, error) {
	params := url.Values{}
	params.Add("limit", strconv.Itoa(limit))
	params.Add("skip", strconv.Itoa(skip))
	if search != "" {
		params.Add("search", search)
	}

	req, err := c.NewRequest(endpoint, params, "")
	if err != nil {
		return &Meta{}, err
	}

	resp, err := c.Do(req, &data)
	if err != nil {
		return &Meta{}, fmt.Errorf("Search:err: %s", err)
	}

	return resp.Meta, nil
}

// Reponse resembles the data returned by the API
type response struct {
	HTTPResponse *http.Response
	Response     interface{}
	Meta         *Meta
	Results      interface{}
}

// Meta represents information about the response. The Disclaimer and License
// appear to be boilerplate, but the Pagination data will be useful
// to assist in iterating over a dataset which contains greater than 100 items.
type Meta struct {
	Disclaimer  string
	License     string
	LastUpdated string     `json:"last_updated"`
	Pagination  Pagination `json:"results"`
}

// Pagination contains information about the returned data, including how many
// records were skipped (Skip), how many records were included (Limit), and
// how many total records exist (Total).
type Pagination struct {
	Skip  int
	Limit int
	Total int
}

// ErrorResponse represents a Response which contains an error and which
// satisfies the Error type
type ErrorResponse struct {
	HTTPResponse *http.Response
	Err          struct {
		StatusCode int
		Code       string
		Message    string
	} `json:"error"`
}

func (r *ErrorResponse) Error() string {
	return fmt.Sprintf("%v %v: %d %v %v",
		r.HTTPResponse.Request.Method, r.HTTPResponse.Request.URL.String(),
		r.Err.StatusCode, r.Err.Code, r.Err.Message)
}

// checkResponse checks the API response for error, and returns it
// if present. A response is considered an error if it has non-http.StatusOK
// code.
func checkResponse(r *http.Response) error {
	if r.StatusCode == http.StatusOK {
		return nil
	}

	resp := new(ErrorResponse)
	resp.HTTPResponse = r

	err := json.NewDecoder(r.Body).Decode(resp)
	if err != nil {
		return fmt.Errorf("CheckResponse:error: %s", err.Error())
	}

	resp.Err.StatusCode = r.StatusCode

	return resp
}
<|endoftext|>